@autobe/benchmark 0.30.0-dev.20260315 → 0.30.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/LICENSE +661 -661
- package/lib/example/AutoBeExampleLogger.js +16 -16
- package/lib/replay/AutoBeReplayDocumentation.js +39 -39
- package/package.json +4 -4
- package/src/example/AutoBeExampleArchiver.ts +381 -381
- package/src/example/AutoBeExampleBenchmark.ts +190 -190
- package/src/example/AutoBeExampleLogger.ts +85 -85
- package/src/example/AutoBeExampleStorage.ts +289 -289
- package/src/example/index.ts +4 -4
- package/src/index.ts +2 -2
- package/src/replay/AutoBeReplayComputer.ts +183 -183
- package/src/replay/AutoBeReplayDocumentation.ts +176 -176
- package/src/replay/AutoBeReplayStorage.ts +116 -116
- package/src/replay/index.ts +3 -3
- package/src/structures/IAutoBeExampleBenchmarkState.ts +30 -30
- package/src/structures/index.ts +1 -1
- package/README.md +0 -261
|
@@ -1,190 +1,190 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AutoBeEvent,
|
|
3
|
-
AutoBeExampleProject,
|
|
4
|
-
AutoBePhase,
|
|
5
|
-
IAutoBeAgent,
|
|
6
|
-
} from "@autobe/interface";
|
|
7
|
-
|
|
8
|
-
import { IAutoBeExampleBenchmarkState } from "../structures/IAutoBeExampleBenchmarkState";
|
|
9
|
-
import { AutoBeExampleArchiver } from "./AutoBeExampleArchiver";
|
|
10
|
-
|
|
11
|
-
export namespace AutoBeExampleBenchmark {
|
|
12
|
-
export interface IContext {
|
|
13
|
-
createAgent: (
|
|
14
|
-
props: AutoBeExampleArchiver.IAgentProps,
|
|
15
|
-
) => Promise<IAutoBeAgent>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const execute = async (
|
|
19
|
-
ctx: IContext,
|
|
20
|
-
props: {
|
|
21
|
-
vendors: string[];
|
|
22
|
-
projects?: AutoBeExampleProject[];
|
|
23
|
-
phases?: AutoBePhase[];
|
|
24
|
-
imagePath?: string;
|
|
25
|
-
progress: (state: IAutoBeExampleBenchmarkState) => void;
|
|
26
|
-
on?: (
|
|
27
|
-
event: AutoBeEvent,
|
|
28
|
-
agent: IAutoBeAgent,
|
|
29
|
-
context: { vendor: string; project: AutoBeExampleProject },
|
|
30
|
-
) => void;
|
|
31
|
-
},
|
|
32
|
-
): Promise<void> => {
|
|
33
|
-
const state: IAutoBeExampleBenchmarkState = {
|
|
34
|
-
vendors: props.vendors.map(
|
|
35
|
-
(vendor): IAutoBeExampleBenchmarkState.IOfVendor => ({
|
|
36
|
-
name: vendor,
|
|
37
|
-
projects: PROJECT_SEQUENCE.filter(
|
|
38
|
-
(p) => !props.projects || props.projects.includes(p),
|
|
39
|
-
).map(
|
|
40
|
-
(project): IAutoBeExampleBenchmarkState.IOfProject => ({
|
|
41
|
-
name: project,
|
|
42
|
-
phases: [],
|
|
43
|
-
success: null,
|
|
44
|
-
started_at: null,
|
|
45
|
-
completed_at: null,
|
|
46
|
-
}),
|
|
47
|
-
),
|
|
48
|
-
}),
|
|
49
|
-
),
|
|
50
|
-
};
|
|
51
|
-
const report = () => props.progress(state);
|
|
52
|
-
await Promise.all(
|
|
53
|
-
state.vendors.map(async (vendor) => {
|
|
54
|
-
await executeVendor(ctx, {
|
|
55
|
-
imagePath: props.imagePath,
|
|
56
|
-
phases: props.phases,
|
|
57
|
-
vendorState: vendor,
|
|
58
|
-
on: props.on,
|
|
59
|
-
report,
|
|
60
|
-
});
|
|
61
|
-
}),
|
|
62
|
-
);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const executeVendor = async (
|
|
66
|
-
ctx: IContext,
|
|
67
|
-
props: {
|
|
68
|
-
imagePath?: string;
|
|
69
|
-
vendorState: IAutoBeExampleBenchmarkState.IOfVendor;
|
|
70
|
-
phases?: AutoBePhase[];
|
|
71
|
-
report: () => void;
|
|
72
|
-
on?: (
|
|
73
|
-
event: AutoBeEvent,
|
|
74
|
-
agent: IAutoBeAgent,
|
|
75
|
-
context: { vendor: string; project: AutoBeExampleProject },
|
|
76
|
-
) => void;
|
|
77
|
-
},
|
|
78
|
-
): Promise<void> => {
|
|
79
|
-
for (const project of props.vendorState.projects)
|
|
80
|
-
await executeProject(ctx, {
|
|
81
|
-
imagePath: props.imagePath,
|
|
82
|
-
vendor: props.vendorState.name,
|
|
83
|
-
projectState: project,
|
|
84
|
-
phases: props.phases,
|
|
85
|
-
report: props.report,
|
|
86
|
-
on: props.on,
|
|
87
|
-
});
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
const executeProject = async (
|
|
91
|
-
ctx: IContext,
|
|
92
|
-
props: {
|
|
93
|
-
vendor: string;
|
|
94
|
-
projectState: IAutoBeExampleBenchmarkState.IOfProject;
|
|
95
|
-
imagePath?: string;
|
|
96
|
-
phases?: AutoBePhase[];
|
|
97
|
-
report: () => void;
|
|
98
|
-
on?: (
|
|
99
|
-
event: AutoBeEvent,
|
|
100
|
-
agent: IAutoBeAgent,
|
|
101
|
-
context: { vendor: string; project: AutoBeExampleProject },
|
|
102
|
-
) => void;
|
|
103
|
-
},
|
|
104
|
-
): Promise<void> => {
|
|
105
|
-
props.projectState.started_at = new Date();
|
|
106
|
-
for (const phase of PHASE_SEQUENCE) {
|
|
107
|
-
if (props.phases && props.phases.includes(phase) === false) continue;
|
|
108
|
-
const phaseState: IAutoBeExampleBenchmarkState.IOfPhase = {
|
|
109
|
-
name: phase,
|
|
110
|
-
snapshot: null,
|
|
111
|
-
success: null,
|
|
112
|
-
started_at: new Date(),
|
|
113
|
-
completed_at: null,
|
|
114
|
-
count: 0,
|
|
115
|
-
};
|
|
116
|
-
props.projectState.phases.push(phaseState);
|
|
117
|
-
try {
|
|
118
|
-
phaseState.started_at = new Date();
|
|
119
|
-
phaseState.completed_at = null;
|
|
120
|
-
phaseState.count = 0;
|
|
121
|
-
const success: boolean = await getArchiver(phase)({
|
|
122
|
-
vendor: props.vendor,
|
|
123
|
-
project: props.projectState.name,
|
|
124
|
-
imagePath: props.imagePath,
|
|
125
|
-
agent: (next) => ctx.createAgent(next),
|
|
126
|
-
on: (s, agent) => {
|
|
127
|
-
++phaseState.count;
|
|
128
|
-
const event = s.event;
|
|
129
|
-
if (
|
|
130
|
-
event.type !== "jsonValidateError" &&
|
|
131
|
-
event.type !== "jsonParseError" &&
|
|
132
|
-
event.type !== "preliminary" &&
|
|
133
|
-
event.type !== "consentFunctionCall"
|
|
134
|
-
)
|
|
135
|
-
phaseState.snapshot = s;
|
|
136
|
-
props.report();
|
|
137
|
-
if (props.on)
|
|
138
|
-
props.on(s.event, agent, {
|
|
139
|
-
vendor: props.vendor,
|
|
140
|
-
project: props.projectState.name,
|
|
141
|
-
});
|
|
142
|
-
},
|
|
143
|
-
});
|
|
144
|
-
phaseState.success = success;
|
|
145
|
-
phaseState.completed_at = new Date();
|
|
146
|
-
props.report();
|
|
147
|
-
} catch (error) {
|
|
148
|
-
console.log(
|
|
149
|
-
props.vendor,
|
|
150
|
-
props.projectState.name,
|
|
151
|
-
phaseState.name,
|
|
152
|
-
error,
|
|
153
|
-
);
|
|
154
|
-
throw error;
|
|
155
|
-
}
|
|
156
|
-
if (phaseState.success === null || phaseState.success === false) break;
|
|
157
|
-
}
|
|
158
|
-
props.projectState.completed_at = new Date();
|
|
159
|
-
props.projectState.success = props.projectState.phases.every(
|
|
160
|
-
(phase) => phase.success === true,
|
|
161
|
-
);
|
|
162
|
-
props.report();
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const getArchiver = (phase: AutoBePhase) => {
|
|
167
|
-
if (phase === "analyze") return AutoBeExampleArchiver.archiveAnalyze;
|
|
168
|
-
else if (phase === "database") return AutoBeExampleArchiver.archivePrisma;
|
|
169
|
-
else if (phase === "interface") return AutoBeExampleArchiver.archiveInterface;
|
|
170
|
-
else if (phase === "test") return AutoBeExampleArchiver.archiveTest;
|
|
171
|
-
else if (phase === "realize") return AutoBeExampleArchiver.archiveRealize;
|
|
172
|
-
phase satisfies never;
|
|
173
|
-
throw new Error(`Unknown phase: ${phase}`);
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
const PROJECT_SEQUENCE = [
|
|
177
|
-
"todo",
|
|
178
|
-
"bbs",
|
|
179
|
-
"reddit",
|
|
180
|
-
"shopping",
|
|
181
|
-
"account",
|
|
182
|
-
"erp",
|
|
183
|
-
] as const;
|
|
184
|
-
const PHASE_SEQUENCE = [
|
|
185
|
-
"analyze",
|
|
186
|
-
"database",
|
|
187
|
-
"interface",
|
|
188
|
-
"test",
|
|
189
|
-
"realize",
|
|
190
|
-
] as const;
|
|
1
|
+
import {
|
|
2
|
+
AutoBeEvent,
|
|
3
|
+
AutoBeExampleProject,
|
|
4
|
+
AutoBePhase,
|
|
5
|
+
IAutoBeAgent,
|
|
6
|
+
} from "@autobe/interface";
|
|
7
|
+
|
|
8
|
+
import { IAutoBeExampleBenchmarkState } from "../structures/IAutoBeExampleBenchmarkState";
|
|
9
|
+
import { AutoBeExampleArchiver } from "./AutoBeExampleArchiver";
|
|
10
|
+
|
|
11
|
+
export namespace AutoBeExampleBenchmark {
|
|
12
|
+
export interface IContext {
|
|
13
|
+
createAgent: (
|
|
14
|
+
props: AutoBeExampleArchiver.IAgentProps,
|
|
15
|
+
) => Promise<IAutoBeAgent>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const execute = async (
|
|
19
|
+
ctx: IContext,
|
|
20
|
+
props: {
|
|
21
|
+
vendors: string[];
|
|
22
|
+
projects?: AutoBeExampleProject[];
|
|
23
|
+
phases?: AutoBePhase[];
|
|
24
|
+
imagePath?: string;
|
|
25
|
+
progress: (state: IAutoBeExampleBenchmarkState) => void;
|
|
26
|
+
on?: (
|
|
27
|
+
event: AutoBeEvent,
|
|
28
|
+
agent: IAutoBeAgent,
|
|
29
|
+
context: { vendor: string; project: AutoBeExampleProject },
|
|
30
|
+
) => void;
|
|
31
|
+
},
|
|
32
|
+
): Promise<void> => {
|
|
33
|
+
const state: IAutoBeExampleBenchmarkState = {
|
|
34
|
+
vendors: props.vendors.map(
|
|
35
|
+
(vendor): IAutoBeExampleBenchmarkState.IOfVendor => ({
|
|
36
|
+
name: vendor,
|
|
37
|
+
projects: PROJECT_SEQUENCE.filter(
|
|
38
|
+
(p) => !props.projects || props.projects.includes(p),
|
|
39
|
+
).map(
|
|
40
|
+
(project): IAutoBeExampleBenchmarkState.IOfProject => ({
|
|
41
|
+
name: project,
|
|
42
|
+
phases: [],
|
|
43
|
+
success: null,
|
|
44
|
+
started_at: null,
|
|
45
|
+
completed_at: null,
|
|
46
|
+
}),
|
|
47
|
+
),
|
|
48
|
+
}),
|
|
49
|
+
),
|
|
50
|
+
};
|
|
51
|
+
const report = () => props.progress(state);
|
|
52
|
+
await Promise.all(
|
|
53
|
+
state.vendors.map(async (vendor) => {
|
|
54
|
+
await executeVendor(ctx, {
|
|
55
|
+
imagePath: props.imagePath,
|
|
56
|
+
phases: props.phases,
|
|
57
|
+
vendorState: vendor,
|
|
58
|
+
on: props.on,
|
|
59
|
+
report,
|
|
60
|
+
});
|
|
61
|
+
}),
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const executeVendor = async (
|
|
66
|
+
ctx: IContext,
|
|
67
|
+
props: {
|
|
68
|
+
imagePath?: string;
|
|
69
|
+
vendorState: IAutoBeExampleBenchmarkState.IOfVendor;
|
|
70
|
+
phases?: AutoBePhase[];
|
|
71
|
+
report: () => void;
|
|
72
|
+
on?: (
|
|
73
|
+
event: AutoBeEvent,
|
|
74
|
+
agent: IAutoBeAgent,
|
|
75
|
+
context: { vendor: string; project: AutoBeExampleProject },
|
|
76
|
+
) => void;
|
|
77
|
+
},
|
|
78
|
+
): Promise<void> => {
|
|
79
|
+
for (const project of props.vendorState.projects)
|
|
80
|
+
await executeProject(ctx, {
|
|
81
|
+
imagePath: props.imagePath,
|
|
82
|
+
vendor: props.vendorState.name,
|
|
83
|
+
projectState: project,
|
|
84
|
+
phases: props.phases,
|
|
85
|
+
report: props.report,
|
|
86
|
+
on: props.on,
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const executeProject = async (
|
|
91
|
+
ctx: IContext,
|
|
92
|
+
props: {
|
|
93
|
+
vendor: string;
|
|
94
|
+
projectState: IAutoBeExampleBenchmarkState.IOfProject;
|
|
95
|
+
imagePath?: string;
|
|
96
|
+
phases?: AutoBePhase[];
|
|
97
|
+
report: () => void;
|
|
98
|
+
on?: (
|
|
99
|
+
event: AutoBeEvent,
|
|
100
|
+
agent: IAutoBeAgent,
|
|
101
|
+
context: { vendor: string; project: AutoBeExampleProject },
|
|
102
|
+
) => void;
|
|
103
|
+
},
|
|
104
|
+
): Promise<void> => {
|
|
105
|
+
props.projectState.started_at = new Date();
|
|
106
|
+
for (const phase of PHASE_SEQUENCE) {
|
|
107
|
+
if (props.phases && props.phases.includes(phase) === false) continue;
|
|
108
|
+
const phaseState: IAutoBeExampleBenchmarkState.IOfPhase = {
|
|
109
|
+
name: phase,
|
|
110
|
+
snapshot: null,
|
|
111
|
+
success: null,
|
|
112
|
+
started_at: new Date(),
|
|
113
|
+
completed_at: null,
|
|
114
|
+
count: 0,
|
|
115
|
+
};
|
|
116
|
+
props.projectState.phases.push(phaseState);
|
|
117
|
+
try {
|
|
118
|
+
phaseState.started_at = new Date();
|
|
119
|
+
phaseState.completed_at = null;
|
|
120
|
+
phaseState.count = 0;
|
|
121
|
+
const success: boolean = await getArchiver(phase)({
|
|
122
|
+
vendor: props.vendor,
|
|
123
|
+
project: props.projectState.name,
|
|
124
|
+
imagePath: props.imagePath,
|
|
125
|
+
agent: (next) => ctx.createAgent(next),
|
|
126
|
+
on: (s, agent) => {
|
|
127
|
+
++phaseState.count;
|
|
128
|
+
const event = s.event;
|
|
129
|
+
if (
|
|
130
|
+
event.type !== "jsonValidateError" &&
|
|
131
|
+
event.type !== "jsonParseError" &&
|
|
132
|
+
event.type !== "preliminary" &&
|
|
133
|
+
event.type !== "consentFunctionCall"
|
|
134
|
+
)
|
|
135
|
+
phaseState.snapshot = s;
|
|
136
|
+
props.report();
|
|
137
|
+
if (props.on)
|
|
138
|
+
props.on(s.event, agent, {
|
|
139
|
+
vendor: props.vendor,
|
|
140
|
+
project: props.projectState.name,
|
|
141
|
+
});
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
phaseState.success = success;
|
|
145
|
+
phaseState.completed_at = new Date();
|
|
146
|
+
props.report();
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.log(
|
|
149
|
+
props.vendor,
|
|
150
|
+
props.projectState.name,
|
|
151
|
+
phaseState.name,
|
|
152
|
+
error,
|
|
153
|
+
);
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
if (phaseState.success === null || phaseState.success === false) break;
|
|
157
|
+
}
|
|
158
|
+
props.projectState.completed_at = new Date();
|
|
159
|
+
props.projectState.success = props.projectState.phases.every(
|
|
160
|
+
(phase) => phase.success === true,
|
|
161
|
+
);
|
|
162
|
+
props.report();
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const getArchiver = (phase: AutoBePhase) => {
|
|
167
|
+
if (phase === "analyze") return AutoBeExampleArchiver.archiveAnalyze;
|
|
168
|
+
else if (phase === "database") return AutoBeExampleArchiver.archivePrisma;
|
|
169
|
+
else if (phase === "interface") return AutoBeExampleArchiver.archiveInterface;
|
|
170
|
+
else if (phase === "test") return AutoBeExampleArchiver.archiveTest;
|
|
171
|
+
else if (phase === "realize") return AutoBeExampleArchiver.archiveRealize;
|
|
172
|
+
phase satisfies never;
|
|
173
|
+
throw new Error(`Unknown phase: ${phase}`);
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const PROJECT_SEQUENCE = [
|
|
177
|
+
"todo",
|
|
178
|
+
"bbs",
|
|
179
|
+
"reddit",
|
|
180
|
+
"shopping",
|
|
181
|
+
"account",
|
|
182
|
+
"erp",
|
|
183
|
+
] as const;
|
|
184
|
+
const PHASE_SEQUENCE = [
|
|
185
|
+
"analyze",
|
|
186
|
+
"database",
|
|
187
|
+
"interface",
|
|
188
|
+
"test",
|
|
189
|
+
"realize",
|
|
190
|
+
] as const;
|
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
import { AutoBeProgressEventBase } from "@autobe/interface";
|
|
2
|
-
import { StringUtil } from "@autobe/utils";
|
|
3
|
-
import typia from "typia";
|
|
4
|
-
|
|
5
|
-
import { IAutoBeExampleBenchmarkState } from "../structures";
|
|
6
|
-
|
|
7
|
-
export namespace AutoBeExampleLogger {
|
|
8
|
-
export const markdown = (state: IAutoBeExampleBenchmarkState): string =>
|
|
9
|
-
StringUtil.trim`
|
|
10
|
-
# AutoBe Example Benchmark Report
|
|
11
|
-
|
|
12
|
-
${markdownIndex(state)}
|
|
13
|
-
|
|
14
|
-
${state.vendors.map(markdownVendor).join("\n\n")}
|
|
15
|
-
`;
|
|
16
|
-
|
|
17
|
-
const markdownIndex = (
|
|
18
|
-
state: IAutoBeExampleBenchmarkState,
|
|
19
|
-
): string => StringUtil.trim`
|
|
20
|
-
## Table of Contents
|
|
21
|
-
|
|
22
|
-
${state.vendors
|
|
23
|
-
.map(
|
|
24
|
-
(vendor) =>
|
|
25
|
-
`- [\`${vendor.name}\`](#${vendor.name
|
|
26
|
-
.replaceAll("/", "")
|
|
27
|
-
.replaceAll(":", "")})`,
|
|
28
|
-
)
|
|
29
|
-
.join("\n")}
|
|
30
|
-
`;
|
|
31
|
-
|
|
32
|
-
const markdownVendor = (
|
|
33
|
-
state: IAutoBeExampleBenchmarkState.IOfVendor,
|
|
34
|
-
): string => StringUtil.trim`
|
|
35
|
-
## \`${state.name}\`
|
|
36
|
-
|
|
37
|
-
Project | Phase | State | Count | Elapsed Time
|
|
38
|
-
:-------|:------|:------|------:|-------------:
|
|
39
|
-
${state.projects.map(markdownProject).join("\n")}
|
|
40
|
-
`;
|
|
41
|
-
|
|
42
|
-
const markdownProject = (
|
|
43
|
-
state: IAutoBeExampleBenchmarkState.IOfProject,
|
|
44
|
-
): string => {
|
|
45
|
-
// yellow circle emoji:
|
|
46
|
-
const phase: IAutoBeExampleBenchmarkState.IOfPhase | undefined =
|
|
47
|
-
state.phases.at(-1);
|
|
48
|
-
return [
|
|
49
|
-
state.name,
|
|
50
|
-
phase?.name ?? "-",
|
|
51
|
-
phase !== undefined && phase.snapshot !== null
|
|
52
|
-
? [
|
|
53
|
-
state.completed_at !== null
|
|
54
|
-
? state.success
|
|
55
|
-
? "🟢 success"
|
|
56
|
-
: "🔴 failure"
|
|
57
|
-
: "🟡",
|
|
58
|
-
`\`${phase.snapshot.event.type}\``,
|
|
59
|
-
...(typia.is<AutoBeProgressEventBase>(phase.snapshot.event)
|
|
60
|
-
? [
|
|
61
|
-
`(${phase.snapshot.event.completed} of ${phase.snapshot.event.total})`,
|
|
62
|
-
]
|
|
63
|
-
: []),
|
|
64
|
-
].join(" ")
|
|
65
|
-
: "-",
|
|
66
|
-
phase?.count.toLocaleString() ?? "0",
|
|
67
|
-
state.started_at !== null
|
|
68
|
-
? elapsedTime({
|
|
69
|
-
started_at: state.started_at,
|
|
70
|
-
completed_at: state.completed_at,
|
|
71
|
-
})
|
|
72
|
-
: "-",
|
|
73
|
-
].join(" | ");
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const elapsedTime = (props: {
|
|
78
|
-
started_at: Date;
|
|
79
|
-
completed_at: Date | null;
|
|
80
|
-
}): string =>
|
|
81
|
-
Math.round(
|
|
82
|
-
((props.completed_at ?? new Date()).getTime() -
|
|
83
|
-
props.started_at.getTime()) /
|
|
84
|
-
1_000,
|
|
85
|
-
).toLocaleString() + " sec";
|
|
1
|
+
import { AutoBeProgressEventBase } from "@autobe/interface";
|
|
2
|
+
import { StringUtil } from "@autobe/utils";
|
|
3
|
+
import typia from "typia";
|
|
4
|
+
|
|
5
|
+
import { IAutoBeExampleBenchmarkState } from "../structures";
|
|
6
|
+
|
|
7
|
+
export namespace AutoBeExampleLogger {
|
|
8
|
+
export const markdown = (state: IAutoBeExampleBenchmarkState): string =>
|
|
9
|
+
StringUtil.trim`
|
|
10
|
+
# AutoBe Example Benchmark Report
|
|
11
|
+
|
|
12
|
+
${markdownIndex(state)}
|
|
13
|
+
|
|
14
|
+
${state.vendors.map(markdownVendor).join("\n\n")}
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const markdownIndex = (
|
|
18
|
+
state: IAutoBeExampleBenchmarkState,
|
|
19
|
+
): string => StringUtil.trim`
|
|
20
|
+
## Table of Contents
|
|
21
|
+
|
|
22
|
+
${state.vendors
|
|
23
|
+
.map(
|
|
24
|
+
(vendor) =>
|
|
25
|
+
`- [\`${vendor.name}\`](#${vendor.name
|
|
26
|
+
.replaceAll("/", "")
|
|
27
|
+
.replaceAll(":", "")})`,
|
|
28
|
+
)
|
|
29
|
+
.join("\n")}
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
const markdownVendor = (
|
|
33
|
+
state: IAutoBeExampleBenchmarkState.IOfVendor,
|
|
34
|
+
): string => StringUtil.trim`
|
|
35
|
+
## \`${state.name}\`
|
|
36
|
+
|
|
37
|
+
Project | Phase | State | Count | Elapsed Time
|
|
38
|
+
:-------|:------|:------|------:|-------------:
|
|
39
|
+
${state.projects.map(markdownProject).join("\n")}
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
const markdownProject = (
|
|
43
|
+
state: IAutoBeExampleBenchmarkState.IOfProject,
|
|
44
|
+
): string => {
|
|
45
|
+
// yellow circle emoji:
|
|
46
|
+
const phase: IAutoBeExampleBenchmarkState.IOfPhase | undefined =
|
|
47
|
+
state.phases.at(-1);
|
|
48
|
+
return [
|
|
49
|
+
state.name,
|
|
50
|
+
phase?.name ?? "-",
|
|
51
|
+
phase !== undefined && phase.snapshot !== null
|
|
52
|
+
? [
|
|
53
|
+
state.completed_at !== null
|
|
54
|
+
? state.success
|
|
55
|
+
? "🟢 success"
|
|
56
|
+
: "🔴 failure"
|
|
57
|
+
: "🟡",
|
|
58
|
+
`\`${phase.snapshot.event.type}\``,
|
|
59
|
+
...(typia.is<AutoBeProgressEventBase>(phase.snapshot.event)
|
|
60
|
+
? [
|
|
61
|
+
`(${phase.snapshot.event.completed} of ${phase.snapshot.event.total})`,
|
|
62
|
+
]
|
|
63
|
+
: []),
|
|
64
|
+
].join(" ")
|
|
65
|
+
: "-",
|
|
66
|
+
phase?.count.toLocaleString() ?? "0",
|
|
67
|
+
state.started_at !== null
|
|
68
|
+
? elapsedTime({
|
|
69
|
+
started_at: state.started_at,
|
|
70
|
+
completed_at: state.completed_at,
|
|
71
|
+
})
|
|
72
|
+
: "-",
|
|
73
|
+
].join(" | ");
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const elapsedTime = (props: {
|
|
78
|
+
started_at: Date;
|
|
79
|
+
completed_at: Date | null;
|
|
80
|
+
}): string =>
|
|
81
|
+
Math.round(
|
|
82
|
+
((props.completed_at ?? new Date()).getTime() -
|
|
83
|
+
props.started_at.getTime()) /
|
|
84
|
+
1_000,
|
|
85
|
+
).toLocaleString() + " sec";
|