@reicek/neataptic-ts 0.1.25 → 0.1.26

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.
Files changed (210) hide show
  1. package/.github/copilot-instructions.md +11 -0
  2. package/.github/skills/trace-analyzer-extension/SKILL.md +3 -3
  3. package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +1 -1
  4. package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +1 -1
  5. package/.github/skills/trace-audit-reporting/SKILL.md +3 -3
  6. package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +1 -1
  7. package/package.json +19 -13
  8. package/plans/Flappy_Bird_Folder_Documentation_Pass.md +4 -4
  9. package/plans/README.md +24 -0
  10. package/plans/Roadmap.md +62 -40
  11. package/plans/analyze-trace-solid-split.plans.md +66 -0
  12. package/plans/architecture-solid-split.plans.md +9 -15
  13. package/plans/asciiMaze-typescript-repair.plans.md +1 -1
  14. package/plans/generate-docs-solid-split.plans.md +87 -0
  15. package/plans/methods-docs.plans.md +25 -1
  16. package/plans/methods-solid-split.plans.md +14 -14
  17. package/plans/neat-docs.plans.md +9 -1
  18. package/plans/neat-test-surface-repair.plans.md +1 -1
  19. package/plans/render-docs-html-solid-split.plans.md +68 -0
  20. package/plans/src-no-explicit-any-cleanup.plans.md +1 -1
  21. package/plans/utils-docs.plans.md +6 -1
  22. package/scripts/analyze-trace/analyze-trace.analysis.ts +479 -0
  23. package/scripts/analyze-trace/analyze-trace.constants.ts +35 -0
  24. package/scripts/analyze-trace/analyze-trace.io.ts +69 -0
  25. package/scripts/analyze-trace/analyze-trace.report.ts +100 -0
  26. package/scripts/analyze-trace/analyze-trace.shared.ts +116 -0
  27. package/scripts/analyze-trace/analyze-trace.ts +45 -0
  28. package/scripts/analyze-trace/analyze-trace.types.ts +72 -0
  29. package/scripts/assets/theme.css +80 -23
  30. package/scripts/copy-examples.ts +239 -0
  31. package/scripts/export-onnx.ts +223 -0
  32. package/scripts/generate-bench-tables.ts +378 -37
  33. package/scripts/generate-docs/generate-docs.constants.ts +107 -0
  34. package/scripts/generate-docs/generate-docs.order.ts +355 -0
  35. package/scripts/generate-docs/generate-docs.state.ts +31 -0
  36. package/scripts/generate-docs/generate-docs.targets.ts +165 -0
  37. package/scripts/generate-docs/generate-docs.ts +63 -0
  38. package/scripts/generate-docs/generate-docs.types.ts +112 -0
  39. package/scripts/generate-docs/output/generate-docs.output.folder-index.utils.ts +167 -0
  40. package/scripts/generate-docs/output/generate-docs.output.ordering.utils.ts +353 -0
  41. package/scripts/generate-docs/output/generate-docs.output.readme.utils.ts +420 -0
  42. package/scripts/generate-docs/output/generate-docs.output.ts +123 -0
  43. package/scripts/generate-docs/output/generate-docs.output.warnings.utils.ts +219 -0
  44. package/scripts/generate-docs/symbols/generate-docs.symbols.collection.utils.ts +365 -0
  45. package/scripts/generate-docs/symbols/generate-docs.symbols.jsdoc.utils.ts +373 -0
  46. package/scripts/generate-docs/symbols/generate-docs.symbols.normalize.utils.ts +155 -0
  47. package/scripts/generate-docs/symbols/generate-docs.symbols.render.utils.ts +149 -0
  48. package/scripts/generate-docs/symbols/generate-docs.symbols.signature.utils.ts +289 -0
  49. package/scripts/generate-docs/symbols/generate-docs.symbols.ts +11 -0
  50. package/scripts/mermaid-cli.mjs +102 -22
  51. package/scripts/mermaid-cli.ts +736 -0
  52. package/scripts/render-docs-html/render-docs-html.assets.ts +54 -0
  53. package/scripts/render-docs-html/render-docs-html.mermaid.ts +245 -0
  54. package/scripts/{render-docs-html.sidebar.ts → render-docs-html/render-docs-html.navigation.ts} +141 -144
  55. package/scripts/render-docs-html/render-docs-html.pages.ts +333 -0
  56. package/scripts/render-docs-html/render-docs-html.shared.ts +333 -0
  57. package/scripts/render-docs-html/render-docs-html.types.ts +42 -0
  58. package/scripts/render-docs-html.ts +23 -587
  59. package/scripts/run-docs.ts +238 -0
  60. package/scripts/write-dist-docs-pkg.ts +40 -0
  61. package/src/README.md +75 -75
  62. package/src/architecture/connection/README.md +5 -5
  63. package/src/architecture/layer/README.md +508 -508
  64. package/src/architecture/network/README.md +1458 -1458
  65. package/src/architecture/network/activate/README.md +694 -694
  66. package/src/architecture/network/bootstrap/README.md +77 -77
  67. package/src/architecture/network/connect/README.md +74 -74
  68. package/src/architecture/network/deterministic/README.md +135 -135
  69. package/src/architecture/network/evolve/README.md +364 -364
  70. package/src/architecture/network/gating/README.md +130 -130
  71. package/src/architecture/network/genetic/README.md +399 -399
  72. package/src/architecture/network/mutate/README.md +897 -897
  73. package/src/architecture/network/onnx/README.md +720 -720
  74. package/src/architecture/network/onnx/export/README.md +728 -728
  75. package/src/architecture/network/onnx/export/layers/README.md +450 -450
  76. package/src/architecture/network/onnx/import/README.md +618 -618
  77. package/src/architecture/network/onnx/schema/README.md +32 -32
  78. package/src/architecture/network/prune/README.md +245 -245
  79. package/src/architecture/network/remove/README.md +135 -135
  80. package/src/architecture/network/runtime/README.md +106 -106
  81. package/src/architecture/network/serialize/README.md +542 -542
  82. package/src/architecture/network/slab/README.md +608 -608
  83. package/src/architecture/network/standalone/README.md +212 -212
  84. package/src/architecture/network/stats/README.md +84 -84
  85. package/src/architecture/network/topology/README.md +465 -465
  86. package/src/architecture/network/training/README.md +200 -200
  87. package/src/architecture/node/README.md +5 -5
  88. package/src/architecture/nodePool/README.md +14 -14
  89. package/src/methods/README.md +99 -99
  90. package/src/methods/activation/README.md +189 -189
  91. package/src/methods/cost/README.md +131 -131
  92. package/src/methods/rate/README.md +86 -86
  93. package/src/multithreading/README.md +77 -77
  94. package/src/multithreading/workers/browser/README.md +8 -8
  95. package/src/multithreading/workers/node/README.md +8 -8
  96. package/src/neat/README.md +148 -148
  97. package/src/neat/adaptive/README.md +120 -120
  98. package/src/neat/adaptive/acceptance/README.md +40 -40
  99. package/src/neat/adaptive/complexity/README.md +137 -137
  100. package/src/neat/adaptive/core/README.md +197 -197
  101. package/src/neat/adaptive/lineage/README.md +90 -90
  102. package/src/neat/adaptive/mutation/README.md +284 -284
  103. package/src/neat/compat/README.md +43 -43
  104. package/src/neat/compat/core/README.md +90 -90
  105. package/src/neat/diversity/README.md +35 -35
  106. package/src/neat/diversity/core/README.md +88 -88
  107. package/src/neat/evaluate/README.md +85 -85
  108. package/src/neat/evaluate/auto-distance/README.md +75 -75
  109. package/src/neat/evaluate/entropy-compat/README.md +37 -37
  110. package/src/neat/evaluate/entropy-sharing/README.md +43 -43
  111. package/src/neat/evaluate/fitness/README.md +23 -23
  112. package/src/neat/evaluate/novelty/README.md +120 -120
  113. package/src/neat/evaluate/objectives/README.md +17 -17
  114. package/src/neat/evaluate/shared/README.md +94 -94
  115. package/src/neat/evolve/README.md +96 -96
  116. package/src/neat/evolve/adaptive/README.md +60 -60
  117. package/src/neat/evolve/objectives/README.md +63 -63
  118. package/src/neat/evolve/offspring/README.md +56 -56
  119. package/src/neat/evolve/population/README.md +171 -171
  120. package/src/neat/evolve/runtime/README.md +79 -79
  121. package/src/neat/evolve/speciation/README.md +74 -74
  122. package/src/neat/evolve/warnings/README.md +10 -10
  123. package/src/neat/export/README.md +114 -114
  124. package/src/neat/helpers/README.md +50 -50
  125. package/src/neat/init/README.md +9 -9
  126. package/src/neat/lineage/core/README.md +101 -101
  127. package/src/neat/multiobjective/category/README.md +74 -74
  128. package/src/neat/multiobjective/crowding/README.md +272 -272
  129. package/src/neat/multiobjective/dominance/README.md +171 -171
  130. package/src/neat/multiobjective/fronts/README.md +68 -68
  131. package/src/neat/multiobjective/metrics/README.md +43 -43
  132. package/src/neat/multiobjective/objectives/README.md +31 -31
  133. package/src/neat/multiobjective/shared/README.md +27 -27
  134. package/src/neat/mutation/README.md +97 -97
  135. package/src/neat/mutation/add-conn/README.md +115 -115
  136. package/src/neat/mutation/add-node/README.md +126 -126
  137. package/src/neat/mutation/flow/README.md +149 -149
  138. package/src/neat/mutation/repair/README.md +185 -185
  139. package/src/neat/mutation/select/README.md +117 -117
  140. package/src/neat/mutation/shared/README.md +32 -32
  141. package/src/neat/objectives/README.md +25 -25
  142. package/src/neat/objectives/core/README.md +67 -67
  143. package/src/neat/pruning/README.md +40 -40
  144. package/src/neat/pruning/core/README.md +171 -171
  145. package/src/neat/pruning/facade/README.md +32 -32
  146. package/src/neat/rng/README.md +104 -104
  147. package/src/neat/rng/core/README.md +137 -137
  148. package/src/neat/rng/facade/README.md +50 -50
  149. package/src/neat/selection/README.md +111 -111
  150. package/src/neat/selection/core/README.md +227 -227
  151. package/src/neat/selection/facade/README.md +61 -61
  152. package/src/neat/shared/README.md +163 -163
  153. package/src/neat/speciation/README.md +31 -31
  154. package/src/neat/speciation/threshold/README.md +35 -35
  155. package/src/neat/species/README.md +25 -25
  156. package/src/neat/species/core/README.md +20 -20
  157. package/src/neat/species/core/shared/README.md +18 -18
  158. package/src/neat/species/history/context/README.md +22 -22
  159. package/src/neat/telemetry/accessors/README.md +58 -58
  160. package/src/neat/telemetry/exports/README.md +233 -233
  161. package/src/neat/telemetry/facade/README.md +252 -252
  162. package/src/neat/telemetry/facade/archive/README.md +57 -57
  163. package/src/neat/telemetry/facade/buffer/README.md +43 -43
  164. package/src/neat/telemetry/facade/lineage/README.md +12 -12
  165. package/src/neat/telemetry/facade/objectives/README.md +44 -44
  166. package/src/neat/telemetry/facade/runtime/README.md +26 -26
  167. package/src/neat/telemetry/facade/species/README.md +27 -27
  168. package/src/neat/telemetry/metrics/README.md +696 -696
  169. package/src/neat/telemetry/recorder/README.md +57 -57
  170. package/src/neat/telemetry/types/README.md +32 -32
  171. package/src/neat/topology-intent/README.md +75 -75
  172. package/src/utils/README.md +193 -193
  173. package/test/examples/asciiMaze/browser-entry/README.md +92 -92
  174. package/test/examples/asciiMaze/dashboardManager/README.md +109 -109
  175. package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +28 -28
  176. package/test/examples/asciiMaze/evolutionEngine/README.md +1527 -1527
  177. package/test/examples/asciiMaze/mazeMovement/README.md +105 -105
  178. package/test/examples/asciiMaze/mazeMovement/finalization/README.md +16 -16
  179. package/test/examples/asciiMaze/mazeMovement/policy/README.md +57 -57
  180. package/test/examples/asciiMaze/mazeMovement/runtime/README.md +52 -52
  181. package/test/examples/asciiMaze/mazeMovement/shaping/README.md +46 -46
  182. package/test/examples/flappy_bird/browser-entry/README.md +508 -508
  183. package/test/examples/flappy_bird/browser-entry/host/README.md +101 -101
  184. package/test/examples/flappy_bird/browser-entry/host/resize/README.md +144 -144
  185. package/test/examples/flappy_bird/browser-entry/network-view/README.md +194 -194
  186. package/test/examples/flappy_bird/browser-entry/playback/README.md +278 -278
  187. package/test/examples/flappy_bird/browser-entry/playback/background/README.md +129 -129
  188. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +502 -502
  189. package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +139 -139
  190. package/test/examples/flappy_bird/browser-entry/playback/snapshot/README.md +10 -10
  191. package/test/examples/flappy_bird/browser-entry/playback/trail/README.md +43 -43
  192. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/README.md +30 -30
  193. package/test/examples/flappy_bird/browser-entry/runtime/README.md +59 -59
  194. package/test/examples/flappy_bird/browser-entry/visualization/README.md +276 -276
  195. package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +16 -16
  196. package/test/examples/flappy_bird/constants/README.md +1070 -1070
  197. package/test/examples/flappy_bird/environment/README.md +22 -22
  198. package/test/examples/flappy_bird/evaluation/README.md +32 -32
  199. package/test/examples/flappy_bird/evaluation/rollout/README.md +141 -141
  200. package/test/examples/flappy_bird/flappy-evolution-worker/README.md +425 -425
  201. package/test/examples/flappy_bird/simulation-shared/README.md +170 -170
  202. package/test/examples/flappy_bird/simulation-shared/observation/README.md +109 -109
  203. package/test/examples/flappy_bird/trainer/README.md +325 -325
  204. package/test/examples/flappy_bird/trainer/evaluation/README.md +74 -74
  205. package/scripts/analyze-trace.ts +0 -590
  206. package/scripts/copy-examples.mjs +0 -114
  207. package/scripts/export-onnx.mjs +0 -86
  208. package/scripts/generate-bench-tables.mjs +0 -182
  209. package/scripts/generate-docs.ts +0 -2900
  210. package/scripts/write-dist-docs-pkg.mjs +0 -16
@@ -0,0 +1,736 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+
6
+ const EXPORT_COMMAND = 'export';
7
+ const VALIDATE_COMMAND = 'validate';
8
+ const SUPPORTED_COMMANDS = new Set<MermaidCommand>([
9
+ EXPORT_COMMAND,
10
+ VALIDATE_COMMAND,
11
+ ]);
12
+ const MERMAID_TEMP_DIRECTORY_PREFIX = 'neatapticts-mermaid-';
13
+ const PUPPETEER_TEMP_DIRECTORY_PREFIX = 'neatapticts-mermaid-puppeteer-';
14
+ const PUPPETEER_CONFIG_FILE_NAME = 'puppeteer-config.json';
15
+ const PUPPETEER_CI_LINUX_ARGS = ['--no-sandbox', '--disable-setuid-sandbox'];
16
+
17
+ type MermaidCommand = typeof EXPORT_COMMAND | typeof VALIDATE_COMMAND;
18
+
19
+ interface ParsedArguments {
20
+ named: Record<string, string>;
21
+ passthrough: string[];
22
+ }
23
+
24
+ interface MermaidCommandContext {
25
+ command: MermaidCommand;
26
+ parsedArguments: ParsedArguments;
27
+ cliPath: string;
28
+ inputPath: string;
29
+ outputPath?: string;
30
+ }
31
+
32
+ interface MermaidCliInvocation {
33
+ argumentsToPass: string[];
34
+ cleanup: () => Promise<void>;
35
+ }
36
+
37
+ type ParsedArgument =
38
+ | {
39
+ kind: 'named';
40
+ name: string;
41
+ value: string;
42
+ consumedExtraArguments: number;
43
+ }
44
+ | {
45
+ kind: 'passthrough';
46
+ passthroughValue: string;
47
+ consumedExtraArguments: number;
48
+ };
49
+
50
+ await main();
51
+
52
+ /**
53
+ * Runs the Mermaid wrapper entrypoint.
54
+ *
55
+ * @returns Resolves after the requested Mermaid command completes.
56
+ */
57
+ async function main(): Promise<void> {
58
+ const commandContext = buildCommandContext(process.argv.slice(2));
59
+ await runCommand(commandContext);
60
+ }
61
+
62
+ /**
63
+ * Executes the requested Mermaid command.
64
+ *
65
+ * @param commandContext - Resolved wrapper command context.
66
+ * @returns Resolves after the requested command completes.
67
+ */
68
+ async function runCommand(
69
+ commandContext: MermaidCommandContext,
70
+ ): Promise<void> {
71
+ if (commandContext.command === VALIDATE_COMMAND) {
72
+ await runValidateCommand(commandContext);
73
+ return;
74
+ }
75
+
76
+ await runExportCommand(commandContext);
77
+ }
78
+
79
+ /**
80
+ * Validates a Mermaid input by rendering it into a temporary SVG.
81
+ *
82
+ * @param commandContext - Resolved wrapper command context.
83
+ * @returns Resolves after the validation render completes.
84
+ */
85
+ async function runValidateCommand(
86
+ commandContext: MermaidCommandContext,
87
+ ): Promise<void> {
88
+ const temporaryValidationDirectoryPath = await createMermaidTempDirectory();
89
+ const temporaryOutputPath = path.join(
90
+ temporaryValidationDirectoryPath,
91
+ 'diagram.svg',
92
+ );
93
+
94
+ const mermaidCliInvocation = await buildMermaidCliInvocation(
95
+ commandContext.parsedArguments,
96
+ buildValidateArguments(
97
+ commandContext.inputPath,
98
+ temporaryOutputPath,
99
+ commandContext.parsedArguments,
100
+ ),
101
+ );
102
+
103
+ try {
104
+ await ensureParentDirectoryExists(temporaryOutputPath);
105
+ await runMermaidCli(
106
+ commandContext.cliPath,
107
+ mermaidCliInvocation.argumentsToPass,
108
+ );
109
+ logValidDiagram(commandContext.inputPath);
110
+ } finally {
111
+ await cleanupInvocation(
112
+ mermaidCliInvocation,
113
+ temporaryValidationDirectoryPath,
114
+ );
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Exports a Mermaid input to the requested output path.
120
+ *
121
+ * @param commandContext - Resolved wrapper command context.
122
+ * @returns Resolves after the export completes.
123
+ */
124
+ async function runExportCommand(
125
+ commandContext: MermaidCommandContext,
126
+ ): Promise<void> {
127
+ const outputPath = commandContext.outputPath;
128
+ if (!outputPath) {
129
+ printUsageAndExit('Missing required --output argument for export.');
130
+ }
131
+
132
+ await ensureParentDirectoryExists(outputPath);
133
+
134
+ const mermaidCliInvocation = await buildMermaidCliInvocation(
135
+ commandContext.parsedArguments,
136
+ buildExportArguments(
137
+ commandContext.inputPath,
138
+ outputPath,
139
+ commandContext.parsedArguments,
140
+ ),
141
+ );
142
+
143
+ try {
144
+ await runMermaidCli(
145
+ commandContext.cliPath,
146
+ mermaidCliInvocation.argumentsToPass,
147
+ );
148
+ logExportedDiagram(outputPath);
149
+ } finally {
150
+ await mermaidCliInvocation.cleanup();
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Builds the resolved command context from raw CLI arguments.
156
+ *
157
+ * @param rawArguments - Raw CLI arguments following the wrapper executable.
158
+ * @returns The validated command context.
159
+ */
160
+ function buildCommandContext(rawArguments: string[]): MermaidCommandContext {
161
+ const commandAndArguments = resolveCommandAndArguments(rawArguments);
162
+ const parsedArguments = parseArguments(commandAndArguments.rawArgs);
163
+
164
+ return {
165
+ command: commandAndArguments.command,
166
+ parsedArguments,
167
+ cliPath: resolveMermaidCliPath(),
168
+ inputPath: resolveRequiredInputPath(parsedArguments),
169
+ outputPath: resolveOptionalOutputPath(
170
+ commandAndArguments.command,
171
+ parsedArguments,
172
+ ),
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Resolves the requested wrapper command and its remaining raw arguments.
178
+ *
179
+ * @param rawArguments - Raw CLI arguments following the wrapper executable.
180
+ * @returns The resolved command packet.
181
+ */
182
+ function resolveCommandAndArguments(rawArguments: string[]): {
183
+ command: MermaidCommand;
184
+ rawArgs: string[];
185
+ } {
186
+ const [command = VALIDATE_COMMAND, ...remainingArguments] = rawArguments;
187
+ ensureSupportedCommand(command);
188
+
189
+ return {
190
+ command,
191
+ rawArgs: remainingArguments,
192
+ };
193
+ }
194
+
195
+ /**
196
+ * Parses raw CLI arguments into named options and pass-through values.
197
+ *
198
+ * @param rawArguments - Raw CLI arguments for the wrapper command.
199
+ * @returns The parsed argument result.
200
+ */
201
+ function parseArguments(rawArguments: string[]): ParsedArguments {
202
+ const parsedArguments: ParsedArguments = { named: {}, passthrough: [] };
203
+
204
+ for (
205
+ let argumentIndex = 0;
206
+ argumentIndex < rawArguments.length;
207
+ argumentIndex += 1
208
+ ) {
209
+ const parsedArgument = parseSingleArgument(rawArguments, argumentIndex);
210
+ applyParsedArgument(parsedArguments, parsedArgument);
211
+ argumentIndex += parsedArgument.consumedExtraArguments;
212
+ }
213
+
214
+ return parsedArguments;
215
+ }
216
+
217
+ /**
218
+ * Parses a single CLI argument token.
219
+ *
220
+ * @param rawArguments - Full raw argument list.
221
+ * @param argumentIndex - Current argument index.
222
+ * @returns Parsed argument packet.
223
+ */
224
+ function parseSingleArgument(
225
+ rawArguments: string[],
226
+ argumentIndex: number,
227
+ ): ParsedArgument {
228
+ const argument = rawArguments[argumentIndex];
229
+ if (!isNamedArgument(argument)) {
230
+ return {
231
+ kind: 'passthrough',
232
+ passthroughValue: argument,
233
+ consumedExtraArguments: 0,
234
+ };
235
+ }
236
+
237
+ return parseNamedArgument(rawArguments, argumentIndex);
238
+ }
239
+
240
+ /**
241
+ * Parses a named CLI argument token.
242
+ *
243
+ * @param rawArguments - Full raw argument list.
244
+ * @param argumentIndex - Current argument index.
245
+ * @returns Parsed named argument packet.
246
+ */
247
+ function parseNamedArgument(
248
+ rawArguments: string[],
249
+ argumentIndex: number,
250
+ ): Extract<ParsedArgument, { kind: 'named' }> {
251
+ const normalizedArgument = rawArguments[argumentIndex].slice(2);
252
+ const [name, inlineValue] = normalizedArgument.split('=', 2);
253
+ if (inlineValue !== undefined) {
254
+ return {
255
+ kind: 'named',
256
+ name,
257
+ value: inlineValue,
258
+ consumedExtraArguments: 0,
259
+ };
260
+ }
261
+
262
+ const nextArgument = rawArguments[argumentIndex + 1];
263
+ if (shouldTreatAsBooleanFlag(nextArgument)) {
264
+ return {
265
+ kind: 'named',
266
+ name,
267
+ value: 'true',
268
+ consumedExtraArguments: 0,
269
+ };
270
+ }
271
+
272
+ return {
273
+ kind: 'named',
274
+ name,
275
+ value: nextArgument,
276
+ consumedExtraArguments: 1,
277
+ };
278
+ }
279
+
280
+ /**
281
+ * Applies a parsed argument packet into the accumulating result.
282
+ *
283
+ * @param parsedArguments - Mutable parsed argument result.
284
+ * @param parsedArgument - Parsed argument packet.
285
+ * @returns Nothing.
286
+ */
287
+ function applyParsedArgument(
288
+ parsedArguments: ParsedArguments,
289
+ parsedArgument: ParsedArgument,
290
+ ): void {
291
+ if (parsedArgument.kind === 'passthrough') {
292
+ parsedArguments.passthrough.push(parsedArgument.passthroughValue);
293
+ return;
294
+ }
295
+
296
+ parsedArguments.named[parsedArgument.name] = parsedArgument.value;
297
+ }
298
+
299
+ /**
300
+ * Resolves the required Mermaid input path.
301
+ *
302
+ * @param parsedArguments - Parsed CLI arguments.
303
+ * @returns The required input path.
304
+ */
305
+ function resolveRequiredInputPath(parsedArguments: ParsedArguments): string {
306
+ const inputPath = resolveNamedValue(parsedArguments, ['input', 'i']);
307
+ if (!inputPath) {
308
+ printUsageAndExit('Missing required --input argument.');
309
+ }
310
+
311
+ return inputPath;
312
+ }
313
+
314
+ /**
315
+ * Resolves the optional export output path, requiring it only for export mode.
316
+ *
317
+ * @param command - Requested wrapper command.
318
+ * @param parsedArguments - Parsed CLI arguments.
319
+ * @returns The required export output path or `undefined` for validation mode.
320
+ */
321
+ function resolveOptionalOutputPath(
322
+ command: MermaidCommand,
323
+ parsedArguments: ParsedArguments,
324
+ ): string | undefined {
325
+ if (command !== EXPORT_COMMAND) {
326
+ return undefined;
327
+ }
328
+
329
+ const outputPath = resolveNamedValue(parsedArguments, ['output', 'o']);
330
+ if (!outputPath) {
331
+ printUsageAndExit('Missing required --output argument for export.');
332
+ }
333
+
334
+ return outputPath;
335
+ }
336
+
337
+ /**
338
+ * Resolves the Mermaid CLI entry path inside local dependencies.
339
+ *
340
+ * @returns Absolute Mermaid CLI entry path.
341
+ */
342
+ function resolveMermaidCliPath(): string {
343
+ return path.resolve(
344
+ process.cwd(),
345
+ 'node_modules',
346
+ '@mermaid-js',
347
+ 'mermaid-cli',
348
+ 'src',
349
+ 'cli.js',
350
+ );
351
+ }
352
+
353
+ /**
354
+ * Builds Mermaid CLI arguments for validation mode.
355
+ *
356
+ * @param inputPath - Mermaid input path.
357
+ * @param temporaryOutputPath - Temporary validation output path.
358
+ * @param parsedArguments - Parsed CLI arguments.
359
+ * @returns Mermaid CLI arguments.
360
+ */
361
+ function buildValidateArguments(
362
+ inputPath: string,
363
+ temporaryOutputPath: string,
364
+ parsedArguments: ParsedArguments,
365
+ ): string[] {
366
+ return buildCommandArguments(inputPath, temporaryOutputPath, parsedArguments);
367
+ }
368
+
369
+ /**
370
+ * Builds Mermaid CLI arguments for export mode.
371
+ *
372
+ * @param inputPath - Mermaid input path.
373
+ * @param outputPath - Export output path.
374
+ * @param parsedArguments - Parsed CLI arguments.
375
+ * @returns Mermaid CLI arguments.
376
+ */
377
+ function buildExportArguments(
378
+ inputPath: string,
379
+ outputPath: string,
380
+ parsedArguments: ParsedArguments,
381
+ ): string[] {
382
+ return buildCommandArguments(inputPath, outputPath, parsedArguments);
383
+ }
384
+
385
+ /**
386
+ * Builds the common Mermaid CLI argument list for input/output operations.
387
+ *
388
+ * @param inputPath - Mermaid input path.
389
+ * @param outputPath - Mermaid output path.
390
+ * @param parsedArguments - Parsed CLI arguments.
391
+ * @returns Mermaid CLI arguments.
392
+ */
393
+ function buildCommandArguments(
394
+ inputPath: string,
395
+ outputPath: string,
396
+ parsedArguments: ParsedArguments,
397
+ ): string[] {
398
+ return [
399
+ '--input',
400
+ inputPath,
401
+ '--output',
402
+ outputPath,
403
+ ...buildPassthroughArguments(parsedArguments, {
404
+ excludedNames: new Set(['input', 'i', 'output', 'o']),
405
+ }),
406
+ ];
407
+ }
408
+
409
+ /**
410
+ * Builds pass-through Mermaid CLI arguments after removing wrapper-owned names.
411
+ *
412
+ * @param parsedArguments - Parsed CLI arguments.
413
+ * @param options - Pass-through filtering options.
414
+ * @returns Mermaid CLI pass-through arguments.
415
+ */
416
+ function buildPassthroughArguments(
417
+ parsedArguments: ParsedArguments,
418
+ options: { excludedNames: ReadonlySet<string> },
419
+ ): string[] {
420
+ const namedArguments = Object.entries(parsedArguments.named)
421
+ .filter(([name]) => !options.excludedNames.has(name))
422
+ .flatMap(([name, value]) => buildNamedArgumentPair(name, value));
423
+
424
+ return [...namedArguments, ...parsedArguments.passthrough];
425
+ }
426
+
427
+ /**
428
+ * Builds the Mermaid CLI invocation, injecting CI-safe Puppeteer config when
429
+ * needed.
430
+ *
431
+ * @param parsedArguments - Parsed CLI arguments.
432
+ * @param baseArguments - Base Mermaid CLI arguments.
433
+ * @returns Prepared Mermaid CLI invocation.
434
+ */
435
+ async function buildMermaidCliInvocation(
436
+ parsedArguments: ParsedArguments,
437
+ baseArguments: string[],
438
+ ): Promise<MermaidCliInvocation> {
439
+ if (!shouldInjectCiLinuxNoSandbox(parsedArguments)) {
440
+ return createDirectInvocation(baseArguments);
441
+ }
442
+
443
+ const temporaryPuppeteerDirectoryPath = await createPuppeteerTempDirectory();
444
+ const puppeteerConfigFilePath = path.join(
445
+ temporaryPuppeteerDirectoryPath,
446
+ PUPPETEER_CONFIG_FILE_NAME,
447
+ );
448
+
449
+ await writePuppeteerConfigFile(puppeteerConfigFilePath);
450
+
451
+ return {
452
+ argumentsToPass: buildPuppeteerConfigArguments(
453
+ puppeteerConfigFilePath,
454
+ baseArguments,
455
+ ),
456
+ cleanup: async () => {
457
+ await rm(temporaryPuppeteerDirectoryPath, {
458
+ recursive: true,
459
+ force: true,
460
+ });
461
+ },
462
+ };
463
+ }
464
+
465
+ /**
466
+ * Runs Mermaid CLI with the prepared argument list.
467
+ *
468
+ * @param cliPath - Mermaid CLI entry path.
469
+ * @param argumentsToPass - Mermaid CLI arguments.
470
+ * @returns Resolves when Mermaid CLI exits successfully.
471
+ */
472
+ async function runMermaidCli(
473
+ cliPath: string,
474
+ argumentsToPass: string[],
475
+ ): Promise<void> {
476
+ await new Promise<void>((resolve, reject) => {
477
+ const childProcess = spawn(
478
+ process.execPath,
479
+ [cliPath, ...argumentsToPass],
480
+ {
481
+ stdio: 'inherit',
482
+ },
483
+ );
484
+
485
+ childProcess.once('exit', (exitCode) => {
486
+ if (exitCode === 0) {
487
+ resolve();
488
+ return;
489
+ }
490
+
491
+ reject(new Error(`Mermaid CLI exited with code ${exitCode ?? 'null'}.`));
492
+ });
493
+ childProcess.once('error', reject);
494
+ });
495
+ }
496
+
497
+ /**
498
+ * Ensures the requested command is supported by this wrapper.
499
+ *
500
+ * @param command - Requested wrapper command.
501
+ * @returns Nothing.
502
+ */
503
+ function ensureSupportedCommand(
504
+ command: string,
505
+ ): asserts command is MermaidCommand {
506
+ if (!SUPPORTED_COMMANDS.has(command as MermaidCommand)) {
507
+ printUsageAndExit(`Unsupported Mermaid CLI command: ${command}`);
508
+ }
509
+ }
510
+
511
+ /**
512
+ * Resolves the first available named value from a list of aliases.
513
+ *
514
+ * @param parsedArguments - Parsed CLI arguments.
515
+ * @param aliases - Named aliases to search in priority order.
516
+ * @returns The resolved named value, if any.
517
+ */
518
+ function resolveNamedValue(
519
+ parsedArguments: ParsedArguments,
520
+ aliases: readonly string[],
521
+ ): string | undefined {
522
+ const matchingAlias = aliases.find(
523
+ (alias) => parsedArguments.named[alias] !== undefined,
524
+ );
525
+
526
+ return matchingAlias ? parsedArguments.named[matchingAlias] : undefined;
527
+ }
528
+
529
+ /**
530
+ * Determines whether a raw token should be parsed as a named argument.
531
+ *
532
+ * @param argument - Raw CLI token.
533
+ * @returns `true` when the token is a named `--flag` argument.
534
+ */
535
+ function isNamedArgument(argument: string | undefined): boolean {
536
+ return argument?.startsWith('--') ?? false;
537
+ }
538
+
539
+ /**
540
+ * Determines whether the next token should leave a named argument as a boolean
541
+ * flag.
542
+ *
543
+ * @param nextArgument - Next raw CLI token.
544
+ * @returns `true` when the argument should be treated as a boolean flag.
545
+ */
546
+ function shouldTreatAsBooleanFlag(nextArgument: string | undefined): boolean {
547
+ return !nextArgument || nextArgument.startsWith('--');
548
+ }
549
+
550
+ /**
551
+ * Builds Mermaid CLI named argument output.
552
+ *
553
+ * @param name - CLI argument name without leading dashes.
554
+ * @param value - CLI argument value.
555
+ * @returns Mermaid CLI argument pair.
556
+ */
557
+ function buildNamedArgumentPair(name: string, value: string): string[] {
558
+ if (value === 'true') {
559
+ return [`--${name}`];
560
+ }
561
+
562
+ return [`--${name}`, value];
563
+ }
564
+
565
+ /**
566
+ * Creates a direct Mermaid CLI invocation with no cleanup work.
567
+ *
568
+ * @param baseArguments - Base Mermaid CLI arguments.
569
+ * @returns Direct Mermaid CLI invocation.
570
+ */
571
+ function createDirectInvocation(baseArguments: string[]): MermaidCliInvocation {
572
+ return {
573
+ argumentsToPass: baseArguments,
574
+ cleanup: async () => {},
575
+ };
576
+ }
577
+
578
+ /**
579
+ * Creates a temporary Mermaid output directory.
580
+ *
581
+ * @returns Temporary Mermaid output directory path.
582
+ */
583
+ async function createMermaidTempDirectory(): Promise<string> {
584
+ return mkdtemp(path.join(os.tmpdir(), MERMAID_TEMP_DIRECTORY_PREFIX));
585
+ }
586
+
587
+ /**
588
+ * Creates a temporary Puppeteer config directory.
589
+ *
590
+ * @returns Temporary Puppeteer config directory path.
591
+ */
592
+ async function createPuppeteerTempDirectory(): Promise<string> {
593
+ return mkdtemp(path.join(os.tmpdir(), PUPPETEER_TEMP_DIRECTORY_PREFIX));
594
+ }
595
+
596
+ /**
597
+ * Writes the injected Puppeteer config file used for Linux CI browser launches.
598
+ *
599
+ * @param puppeteerConfigFilePath - Target Puppeteer config path.
600
+ * @returns Resolves when the config file is written.
601
+ */
602
+ async function writePuppeteerConfigFile(
603
+ puppeteerConfigFilePath: string,
604
+ ): Promise<void> {
605
+ await writeFile(
606
+ puppeteerConfigFilePath,
607
+ JSON.stringify({ args: PUPPETEER_CI_LINUX_ARGS }),
608
+ );
609
+ }
610
+
611
+ /**
612
+ * Builds Mermaid CLI arguments that reference the injected Puppeteer config
613
+ * file.
614
+ *
615
+ * @param puppeteerConfigFilePath - Injected Puppeteer config path.
616
+ * @param baseArguments - Base Mermaid CLI arguments.
617
+ * @returns Mermaid CLI arguments.
618
+ */
619
+ function buildPuppeteerConfigArguments(
620
+ puppeteerConfigFilePath: string,
621
+ baseArguments: string[],
622
+ ): string[] {
623
+ return ['--puppeteerConfigFile', puppeteerConfigFilePath, ...baseArguments];
624
+ }
625
+
626
+ /**
627
+ * Determines whether the Linux CI sandbox workaround should be injected.
628
+ *
629
+ * @param parsedArguments - Parsed CLI arguments.
630
+ * @returns `true` when the wrapper should inject a Puppeteer config.
631
+ */
632
+ function shouldInjectCiLinuxNoSandbox(
633
+ parsedArguments: ParsedArguments,
634
+ ): boolean {
635
+ return (
636
+ isLinuxPlatform() &&
637
+ isContinuousIntegrationEnvironment() &&
638
+ !hasExplicitPuppeteerConfig(parsedArguments)
639
+ );
640
+ }
641
+
642
+ /**
643
+ * Determines whether the current process is running on Linux.
644
+ *
645
+ * @returns `true` when running on Linux.
646
+ */
647
+ function isLinuxPlatform(): boolean {
648
+ return process.platform === 'linux';
649
+ }
650
+
651
+ /**
652
+ * Determines whether the current process is running in CI.
653
+ *
654
+ * @returns `true` when the environment matches CI or GitHub Actions.
655
+ */
656
+ function isContinuousIntegrationEnvironment(): boolean {
657
+ return process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
658
+ }
659
+
660
+ /**
661
+ * Determines whether the caller already supplied a Puppeteer config override.
662
+ *
663
+ * @param parsedArguments - Parsed CLI arguments.
664
+ * @returns `true` when an explicit Puppeteer config is already present.
665
+ */
666
+ function hasExplicitPuppeteerConfig(parsedArguments: ParsedArguments): boolean {
667
+ return (
668
+ parsedArguments.named.puppeteerConfigFile !== undefined ||
669
+ parsedArguments.named.p !== undefined ||
670
+ parsedArguments.passthrough.includes('--puppeteerConfigFile') ||
671
+ parsedArguments.passthrough.includes('-p')
672
+ );
673
+ }
674
+
675
+ /**
676
+ * Ensures the parent directory for a file path exists.
677
+ *
678
+ * @param filePath - Target file path.
679
+ * @returns Resolves when the parent directory exists.
680
+ */
681
+ async function ensureParentDirectoryExists(filePath: string): Promise<void> {
682
+ await mkdir(path.dirname(path.resolve(filePath)), { recursive: true });
683
+ }
684
+
685
+ /**
686
+ * Cleans up a prepared Mermaid invocation and an optional extra temp directory.
687
+ *
688
+ * @param mermaidCliInvocation - Prepared Mermaid invocation.
689
+ * @param extraDirectoryPath - Additional temporary directory path.
690
+ * @returns Resolves after cleanup completes.
691
+ */
692
+ async function cleanupInvocation(
693
+ mermaidCliInvocation: MermaidCliInvocation,
694
+ extraDirectoryPath: string,
695
+ ): Promise<void> {
696
+ await mermaidCliInvocation.cleanup();
697
+ await rm(extraDirectoryPath, { recursive: true, force: true });
698
+ }
699
+
700
+ /**
701
+ * Logs a successful Mermaid validation.
702
+ *
703
+ * @param inputPath - Validated Mermaid input path.
704
+ * @returns Nothing.
705
+ */
706
+ function logValidDiagram(inputPath: string): void {
707
+ console.log(`[mermaid] Valid diagram: ${inputPath}`);
708
+ }
709
+
710
+ /**
711
+ * Logs a successful Mermaid export.
712
+ *
713
+ * @param outputPath - Mermaid export output path.
714
+ * @returns Nothing.
715
+ */
716
+ function logExportedDiagram(outputPath: string): void {
717
+ console.log(`[mermaid] Exported diagram to ${outputPath}`);
718
+ }
719
+
720
+ /**
721
+ * Prints wrapper usage information and exits the process.
722
+ *
723
+ * @param message - Error message shown before usage text.
724
+ * @returns Never returns.
725
+ */
726
+ function printUsageAndExit(message: string): never {
727
+ console.error(`[mermaid] ${message}`);
728
+ console.error(
729
+ [
730
+ 'Usage:',
731
+ ' npm run docs:mermaid:validate -- --input path/to/diagram.mmd [extra mmdc args]',
732
+ ' npm run docs:mermaid:export -- --input path/to/diagram.mmd --output path/to/diagram.svg [extra mmdc args]',
733
+ ].join('\n'),
734
+ );
735
+ process.exit(1);
736
+ }