Skip to content

Commit 59a30cd

Browse files
committed
feat(export): add littlehorse real mode
1 parent 405f875 commit 59a30cd

File tree

3 files changed

+86
-26
lines changed

3 files changed

+86
-26
lines changed

src/command-line.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ Targets:
166166
167167
Options:
168168
--with-annotations Include annotations and document metadata in supported Markdown and HTML exports
169+
--littlehorse-real Emit a LittleHorse scaffold without comment-only lines
169170
-h, --help Show this help
170171
171172
Note:
@@ -272,7 +273,7 @@ ${docs}`);
272273
console.log(`orgscript export littlehorse
273274
274275
Usage:
275-
orgscript export littlehorse <file>
276+
orgscript export littlehorse <file> [--littlehorse-real]
276277
277278
${docs}`);
278279
return;
@@ -560,7 +561,11 @@ function run(args) {
560561
}
561562

562563
try {
563-
process.stdout.write(toLittleHorseSkeleton(toCanonicalModel(result.ast)));
564+
process.stdout.write(
565+
toLittleHorseSkeleton(toCanonicalModel(result.ast), {
566+
realCode: options.littlehorseReal,
567+
})
568+
);
564569
process.exit(0);
565570
} catch (error) {
566571
console.error(`Cannot export LittleHorse from ${absolutePath}: ${error.message}`);
@@ -783,6 +788,7 @@ function parseArgs(args) {
783788
check: false,
784789
json: false,
785790
withAnnotations: false,
791+
littlehorseReal: false,
786792
help: false,
787793
version: false,
788794
positionals: [],
@@ -814,6 +820,11 @@ function parseArgs(args) {
814820
continue;
815821
}
816822

823+
if (argument === "--littlehorse-real") {
824+
options.littlehorseReal = true;
825+
continue;
826+
}
827+
817828
options.positionals.push(argument);
818829
}
819830

src/export-littlehorse.js

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,54 @@
1-
function toLittleHorseSkeleton(model) {
1+
function toLittleHorseSkeleton(model, options = {}) {
2+
const realCode = options.realCode === true;
23
const processes = (model.body || []).filter((node) => node.type === "process");
34

45
if (processes.length === 0) {
56
throw new Error("No LittleHorse-exportable blocks found. Supported block types: process.");
67
}
78

8-
const lines = [
9-
"// OrgScript -> LittleHorse workflow skeleton",
10-
"// This is a scaffold. Translate it to your LittleHorse SDK and task definitions.",
11-
"",
12-
];
9+
const lines = [];
10+
if (!realCode) {
11+
lines.push(
12+
"// OrgScript -> LittleHorse workflow skeleton",
13+
"// This is a scaffold. Translate it to your LittleHorse SDK and task definitions.",
14+
""
15+
);
16+
}
1317

1418
processes.forEach((processNode) => {
1519
const className = sanitizeClassName(processNode.name);
1620
const workflowName = toKebabName(processNode.name);
1721
lines.push(`public final class ${className}Workflow {`);
18-
lines.push(" // TODO: adapt this skeleton to your LittleHorse SDK version.");
22+
if (!realCode) {
23+
lines.push(" // TODO: adapt this skeleton to your LittleHorse SDK version.");
24+
}
1925
lines.push(" public static Workflow getWorkflow() {");
2026
lines.push(` return new WorkflowImpl("${workflowName}", wf -> {`);
21-
lines.push(` // Process: ${processNode.name}`);
27+
if (!realCode) {
28+
lines.push(` // Process: ${processNode.name}`);
29+
}
2230
const declarations = renderDeclarations(processNode.body || [], 6);
2331
if (declarations.length > 0) {
24-
lines.push(" // TODO: declare variables and task definitions");
32+
if (!realCode) {
33+
lines.push(" // TODO: declare variables and task definitions");
34+
}
2535
lines.push(...declarations);
26-
lines.push("");
36+
if (!realCode) {
37+
lines.push("");
38+
}
2739
} else {
28-
lines.push(" // TODO: declare variables and task definitions");
40+
if (!realCode) {
41+
lines.push(" // TODO: declare variables and task definitions");
42+
}
2943
}
3044

31-
const bodyLines = renderStatements(processNode.body || [], 6);
45+
const bodyLines = renderStatements(processNode.body || [], 6, { realCode });
3246
if (bodyLines.length > 0) {
3347
lines.push(...bodyLines);
3448
} else {
35-
lines.push(" // TODO: add workflow steps");
49+
if (!realCode) {
50+
lines.push(" // TODO: add workflow steps");
51+
}
3652
}
3753

3854
lines.push(" });");
@@ -172,56 +188,65 @@ function renderDeclaration(entry) {
172188
return `var ${variableName} = wf.declare${typeSuffix}("${variableName}");`;
173189
}
174190

175-
function renderStatements(statements, indentSize) {
191+
function renderStatements(statements, indentSize, options = {}) {
176192
const lines = [];
177193
const indent = " ".repeat(indentSize);
194+
const realCode = options.realCode === true;
178195

179196
for (const statement of statements) {
180197
if (statement.type === "when") {
181-
lines.push(`${indent}// when ${statement.trigger || "unknown"}`);
198+
if (!realCode) {
199+
lines.push(`${indent}// when ${statement.trigger || "unknown"}`);
200+
}
182201
continue;
183202
}
184203

185204
if (statement.type === "if") {
186205
lines.push(`${indent}wf.doIf(/* ${formatCondition(statement.condition)} */, ifBody -> {`);
187-
lines.push(...renderStatements(statement.then || [], indentSize + 2));
206+
lines.push(...renderStatements(statement.then || [], indentSize + 2, options));
188207
lines.push(`${indent}})`);
189208

190209
const elseIfBranches = statement.elseIf || [];
191210
for (const branch of elseIfBranches) {
192211
lines.push(`${indent}.doElseIf(/* ${formatCondition(branch.condition)} */, elseIfBody -> {`);
193-
lines.push(...renderStatements(branch.then || [], indentSize + 2));
212+
lines.push(...renderStatements(branch.then || [], indentSize + 2, options));
194213
lines.push(`${indent}})`);
195214
}
196215

197216
if (statement.else && (statement.else.body || []).length > 0) {
198217
lines.push(`${indent}.doElse(elseBody -> {`);
199-
lines.push(...renderStatements(statement.else.body || [], indentSize + 2));
218+
lines.push(...renderStatements(statement.else.body || [], indentSize + 2, options));
200219
lines.push(`${indent}});`);
201220
} else {
202-
lines.push(`${indent};`);
221+
const lastIndex = lines.length - 1;
222+
lines[lastIndex] = `${lines[lastIndex]};`;
203223
}
204224
continue;
205225
}
206226

207227
if (statement.type === "stop") {
208-
lines.push(`${indent}// stop`);
228+
if (!realCode) {
229+
lines.push(`${indent}// stop`);
230+
}
209231
continue;
210232
}
211233

212-
const action = formatAction(statement);
213-
if (action) {
234+
const action = formatAction(statement, { realCode });
235+
if (action && (!realCode || !action.startsWith("//"))) {
214236
lines.push(`${indent}${action}`);
215237
continue;
216238
}
217239

218-
lines.push(`${indent}// ${statement.type}`);
240+
if (!realCode) {
241+
lines.push(`${indent}// ${statement.type}`);
242+
}
219243
}
220244

221245
return lines;
222246
}
223247

224-
function formatAction(statement) {
248+
function formatAction(statement, options = {}) {
249+
const realCode = options.realCode === true;
225250
if (statement.type === "assign") {
226251
return `// assign ${statement.target || "?"} = ${formatExpression(statement.value)}`;
227252
}
@@ -250,6 +275,9 @@ function formatAction(statement) {
250275
return `wf.execute("require", "${requirement}");`;
251276
}
252277

278+
if (!realCode) {
279+
return `// ${statement.type}`;
280+
}
253281
return null;
254282
}
255283

tests/run.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,27 @@ function testCliDiagnosticsAndExitCodes() {
449449
"Expected LittleHorse skeleton header"
450450
);
451451

452+
const exportLittleHorseReal = runCli([
453+
cliPath,
454+
"export",
455+
"littlehorse",
456+
"./examples/craft-business-lead-to-order.orgs",
457+
"--littlehorse-real",
458+
]);
459+
assert.strictEqual(
460+
exportLittleHorseReal.status,
461+
0,
462+
"Expected export littlehorse --littlehorse-real to succeed"
463+
);
464+
assert.ok(
465+
exportLittleHorseReal.stdout.includes("WorkflowImpl(\"craft-business-lead-to-order\""),
466+
"Expected LittleHorse real scaffold workflow name"
467+
);
468+
assert.ok(
469+
!exportLittleHorseReal.stdout.includes("OrgScript -> LittleHorse workflow skeleton"),
470+
"Expected real scaffold to omit header comments"
471+
);
472+
452473
const exportGraph = runCli([
453474
cliPath,
454475
"export",

0 commit comments

Comments
 (0)