@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.
- package/.github/copilot-instructions.md +11 -0
- package/.github/skills/trace-analyzer-extension/SKILL.md +3 -3
- package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +1 -1
- package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +1 -1
- package/.github/skills/trace-audit-reporting/SKILL.md +3 -3
- package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +1 -1
- package/package.json +19 -13
- package/plans/Flappy_Bird_Folder_Documentation_Pass.md +4 -4
- package/plans/README.md +24 -0
- package/plans/Roadmap.md +62 -40
- package/plans/analyze-trace-solid-split.plans.md +66 -0
- package/plans/architecture-solid-split.plans.md +9 -15
- package/plans/asciiMaze-typescript-repair.plans.md +1 -1
- package/plans/generate-docs-solid-split.plans.md +87 -0
- package/plans/methods-docs.plans.md +25 -1
- package/plans/methods-solid-split.plans.md +14 -14
- package/plans/neat-docs.plans.md +9 -1
- package/plans/neat-test-surface-repair.plans.md +1 -1
- package/plans/render-docs-html-solid-split.plans.md +68 -0
- package/plans/src-no-explicit-any-cleanup.plans.md +1 -1
- package/plans/utils-docs.plans.md +6 -1
- package/scripts/analyze-trace/analyze-trace.analysis.ts +479 -0
- package/scripts/analyze-trace/analyze-trace.constants.ts +35 -0
- package/scripts/analyze-trace/analyze-trace.io.ts +69 -0
- package/scripts/analyze-trace/analyze-trace.report.ts +100 -0
- package/scripts/analyze-trace/analyze-trace.shared.ts +116 -0
- package/scripts/analyze-trace/analyze-trace.ts +45 -0
- package/scripts/analyze-trace/analyze-trace.types.ts +72 -0
- package/scripts/assets/theme.css +80 -23
- package/scripts/copy-examples.ts +239 -0
- package/scripts/export-onnx.ts +223 -0
- package/scripts/generate-bench-tables.ts +378 -37
- package/scripts/generate-docs/generate-docs.constants.ts +107 -0
- package/scripts/generate-docs/generate-docs.order.ts +355 -0
- package/scripts/generate-docs/generate-docs.state.ts +31 -0
- package/scripts/generate-docs/generate-docs.targets.ts +165 -0
- package/scripts/generate-docs/generate-docs.ts +63 -0
- package/scripts/generate-docs/generate-docs.types.ts +112 -0
- package/scripts/generate-docs/output/generate-docs.output.folder-index.utils.ts +167 -0
- package/scripts/generate-docs/output/generate-docs.output.ordering.utils.ts +353 -0
- package/scripts/generate-docs/output/generate-docs.output.readme.utils.ts +420 -0
- package/scripts/generate-docs/output/generate-docs.output.ts +123 -0
- package/scripts/generate-docs/output/generate-docs.output.warnings.utils.ts +219 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.collection.utils.ts +365 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.jsdoc.utils.ts +373 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.normalize.utils.ts +155 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.render.utils.ts +149 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.signature.utils.ts +289 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.ts +11 -0
- package/scripts/mermaid-cli.mjs +102 -22
- package/scripts/mermaid-cli.ts +736 -0
- package/scripts/render-docs-html/render-docs-html.assets.ts +54 -0
- package/scripts/render-docs-html/render-docs-html.mermaid.ts +245 -0
- package/scripts/{render-docs-html.sidebar.ts → render-docs-html/render-docs-html.navigation.ts} +141 -144
- package/scripts/render-docs-html/render-docs-html.pages.ts +333 -0
- package/scripts/render-docs-html/render-docs-html.shared.ts +333 -0
- package/scripts/render-docs-html/render-docs-html.types.ts +42 -0
- package/scripts/render-docs-html.ts +23 -587
- package/scripts/run-docs.ts +238 -0
- package/scripts/write-dist-docs-pkg.ts +40 -0
- package/src/README.md +75 -75
- package/src/architecture/connection/README.md +5 -5
- package/src/architecture/layer/README.md +508 -508
- package/src/architecture/network/README.md +1458 -1458
- package/src/architecture/network/activate/README.md +694 -694
- package/src/architecture/network/bootstrap/README.md +77 -77
- package/src/architecture/network/connect/README.md +74 -74
- package/src/architecture/network/deterministic/README.md +135 -135
- package/src/architecture/network/evolve/README.md +364 -364
- package/src/architecture/network/gating/README.md +130 -130
- package/src/architecture/network/genetic/README.md +399 -399
- package/src/architecture/network/mutate/README.md +897 -897
- package/src/architecture/network/onnx/README.md +720 -720
- package/src/architecture/network/onnx/export/README.md +728 -728
- package/src/architecture/network/onnx/export/layers/README.md +450 -450
- package/src/architecture/network/onnx/import/README.md +618 -618
- package/src/architecture/network/onnx/schema/README.md +32 -32
- package/src/architecture/network/prune/README.md +245 -245
- package/src/architecture/network/remove/README.md +135 -135
- package/src/architecture/network/runtime/README.md +106 -106
- package/src/architecture/network/serialize/README.md +542 -542
- package/src/architecture/network/slab/README.md +608 -608
- package/src/architecture/network/standalone/README.md +212 -212
- package/src/architecture/network/stats/README.md +84 -84
- package/src/architecture/network/topology/README.md +465 -465
- package/src/architecture/network/training/README.md +200 -200
- package/src/architecture/node/README.md +5 -5
- package/src/architecture/nodePool/README.md +14 -14
- package/src/methods/README.md +99 -99
- package/src/methods/activation/README.md +189 -189
- package/src/methods/cost/README.md +131 -131
- package/src/methods/rate/README.md +86 -86
- package/src/multithreading/README.md +77 -77
- package/src/multithreading/workers/browser/README.md +8 -8
- package/src/multithreading/workers/node/README.md +8 -8
- package/src/neat/README.md +148 -148
- package/src/neat/adaptive/README.md +120 -120
- package/src/neat/adaptive/acceptance/README.md +40 -40
- package/src/neat/adaptive/complexity/README.md +137 -137
- package/src/neat/adaptive/core/README.md +197 -197
- package/src/neat/adaptive/lineage/README.md +90 -90
- package/src/neat/adaptive/mutation/README.md +284 -284
- package/src/neat/compat/README.md +43 -43
- package/src/neat/compat/core/README.md +90 -90
- package/src/neat/diversity/README.md +35 -35
- package/src/neat/diversity/core/README.md +88 -88
- package/src/neat/evaluate/README.md +85 -85
- package/src/neat/evaluate/auto-distance/README.md +75 -75
- package/src/neat/evaluate/entropy-compat/README.md +37 -37
- package/src/neat/evaluate/entropy-sharing/README.md +43 -43
- package/src/neat/evaluate/fitness/README.md +23 -23
- package/src/neat/evaluate/novelty/README.md +120 -120
- package/src/neat/evaluate/objectives/README.md +17 -17
- package/src/neat/evaluate/shared/README.md +94 -94
- package/src/neat/evolve/README.md +96 -96
- package/src/neat/evolve/adaptive/README.md +60 -60
- package/src/neat/evolve/objectives/README.md +63 -63
- package/src/neat/evolve/offspring/README.md +56 -56
- package/src/neat/evolve/population/README.md +171 -171
- package/src/neat/evolve/runtime/README.md +79 -79
- package/src/neat/evolve/speciation/README.md +74 -74
- package/src/neat/evolve/warnings/README.md +10 -10
- package/src/neat/export/README.md +114 -114
- package/src/neat/helpers/README.md +50 -50
- package/src/neat/init/README.md +9 -9
- package/src/neat/lineage/core/README.md +101 -101
- package/src/neat/multiobjective/category/README.md +74 -74
- package/src/neat/multiobjective/crowding/README.md +272 -272
- package/src/neat/multiobjective/dominance/README.md +171 -171
- package/src/neat/multiobjective/fronts/README.md +68 -68
- package/src/neat/multiobjective/metrics/README.md +43 -43
- package/src/neat/multiobjective/objectives/README.md +31 -31
- package/src/neat/multiobjective/shared/README.md +27 -27
- package/src/neat/mutation/README.md +97 -97
- package/src/neat/mutation/add-conn/README.md +115 -115
- package/src/neat/mutation/add-node/README.md +126 -126
- package/src/neat/mutation/flow/README.md +149 -149
- package/src/neat/mutation/repair/README.md +185 -185
- package/src/neat/mutation/select/README.md +117 -117
- package/src/neat/mutation/shared/README.md +32 -32
- package/src/neat/objectives/README.md +25 -25
- package/src/neat/objectives/core/README.md +67 -67
- package/src/neat/pruning/README.md +40 -40
- package/src/neat/pruning/core/README.md +171 -171
- package/src/neat/pruning/facade/README.md +32 -32
- package/src/neat/rng/README.md +104 -104
- package/src/neat/rng/core/README.md +137 -137
- package/src/neat/rng/facade/README.md +50 -50
- package/src/neat/selection/README.md +111 -111
- package/src/neat/selection/core/README.md +227 -227
- package/src/neat/selection/facade/README.md +61 -61
- package/src/neat/shared/README.md +163 -163
- package/src/neat/speciation/README.md +31 -31
- package/src/neat/speciation/threshold/README.md +35 -35
- package/src/neat/species/README.md +25 -25
- package/src/neat/species/core/README.md +20 -20
- package/src/neat/species/core/shared/README.md +18 -18
- package/src/neat/species/history/context/README.md +22 -22
- package/src/neat/telemetry/accessors/README.md +58 -58
- package/src/neat/telemetry/exports/README.md +233 -233
- package/src/neat/telemetry/facade/README.md +252 -252
- package/src/neat/telemetry/facade/archive/README.md +57 -57
- package/src/neat/telemetry/facade/buffer/README.md +43 -43
- package/src/neat/telemetry/facade/lineage/README.md +12 -12
- package/src/neat/telemetry/facade/objectives/README.md +44 -44
- package/src/neat/telemetry/facade/runtime/README.md +26 -26
- package/src/neat/telemetry/facade/species/README.md +27 -27
- package/src/neat/telemetry/metrics/README.md +696 -696
- package/src/neat/telemetry/recorder/README.md +57 -57
- package/src/neat/telemetry/types/README.md +32 -32
- package/src/neat/topology-intent/README.md +75 -75
- package/src/utils/README.md +193 -193
- package/test/examples/asciiMaze/browser-entry/README.md +92 -92
- package/test/examples/asciiMaze/dashboardManager/README.md +109 -109
- package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +28 -28
- package/test/examples/asciiMaze/evolutionEngine/README.md +1527 -1527
- package/test/examples/asciiMaze/mazeMovement/README.md +105 -105
- package/test/examples/asciiMaze/mazeMovement/finalization/README.md +16 -16
- package/test/examples/asciiMaze/mazeMovement/policy/README.md +57 -57
- package/test/examples/asciiMaze/mazeMovement/runtime/README.md +52 -52
- package/test/examples/asciiMaze/mazeMovement/shaping/README.md +46 -46
- package/test/examples/flappy_bird/browser-entry/README.md +508 -508
- package/test/examples/flappy_bird/browser-entry/host/README.md +101 -101
- package/test/examples/flappy_bird/browser-entry/host/resize/README.md +144 -144
- package/test/examples/flappy_bird/browser-entry/network-view/README.md +194 -194
- package/test/examples/flappy_bird/browser-entry/playback/README.md +278 -278
- package/test/examples/flappy_bird/browser-entry/playback/background/README.md +129 -129
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +502 -502
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +139 -139
- package/test/examples/flappy_bird/browser-entry/playback/snapshot/README.md +10 -10
- package/test/examples/flappy_bird/browser-entry/playback/trail/README.md +43 -43
- package/test/examples/flappy_bird/browser-entry/playback/worker-channel/README.md +30 -30
- package/test/examples/flappy_bird/browser-entry/runtime/README.md +59 -59
- package/test/examples/flappy_bird/browser-entry/visualization/README.md +276 -276
- package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +16 -16
- package/test/examples/flappy_bird/constants/README.md +1070 -1070
- package/test/examples/flappy_bird/environment/README.md +22 -22
- package/test/examples/flappy_bird/evaluation/README.md +32 -32
- package/test/examples/flappy_bird/evaluation/rollout/README.md +141 -141
- package/test/examples/flappy_bird/flappy-evolution-worker/README.md +425 -425
- package/test/examples/flappy_bird/simulation-shared/README.md +170 -170
- package/test/examples/flappy_bird/simulation-shared/observation/README.md +109 -109
- package/test/examples/flappy_bird/trainer/README.md +325 -325
- package/test/examples/flappy_bird/trainer/evaluation/README.md +74 -74
- package/scripts/analyze-trace.ts +0 -590
- package/scripts/copy-examples.mjs +0 -114
- package/scripts/export-onnx.mjs +0 -86
- package/scripts/generate-bench-tables.mjs +0 -182
- package/scripts/generate-docs.ts +0 -2900
- package/scripts/write-dist-docs-pkg.mjs +0 -16
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { Primitive } from './analyze-trace.types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Safely resolves a nested primitive value from a trace event args object.
|
|
5
|
+
*
|
|
6
|
+
* @param value - Candidate object tree.
|
|
7
|
+
* @param pathSegments - Nested path segments to follow.
|
|
8
|
+
* @returns Primitive value when the path resolves cleanly.
|
|
9
|
+
*/
|
|
10
|
+
export function readNestedPrimitive(
|
|
11
|
+
value: unknown,
|
|
12
|
+
pathSegments: readonly string[],
|
|
13
|
+
): Primitive {
|
|
14
|
+
let currentValue: unknown = value;
|
|
15
|
+
|
|
16
|
+
for (const pathSegment of pathSegments) {
|
|
17
|
+
if (!currentValue || typeof currentValue !== 'object') {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
currentValue = (currentValue as Record<string, unknown>)[pathSegment];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (
|
|
25
|
+
currentValue == null ||
|
|
26
|
+
typeof currentValue === 'string' ||
|
|
27
|
+
typeof currentValue === 'number' ||
|
|
28
|
+
typeof currentValue === 'boolean'
|
|
29
|
+
) {
|
|
30
|
+
return currentValue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Formats a duration in milliseconds for stable textual output.
|
|
38
|
+
*
|
|
39
|
+
* @param durationMs - Duration in milliseconds.
|
|
40
|
+
* @returns Fixed two-decimal duration string.
|
|
41
|
+
*/
|
|
42
|
+
export function formatMs(durationMs: number): string {
|
|
43
|
+
return `${durationMs.toFixed(2)}ms`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Computes a nearest-rank percentile from an already sorted numeric array.
|
|
48
|
+
*
|
|
49
|
+
* @param sortedDurations - Sorted numeric sample set.
|
|
50
|
+
* @param rank - Percentile rank in the inclusive range `[0, 1]`.
|
|
51
|
+
* @returns Percentile value or `0` when the list is empty.
|
|
52
|
+
*/
|
|
53
|
+
export function percentile(
|
|
54
|
+
sortedDurations: readonly number[],
|
|
55
|
+
rank: number,
|
|
56
|
+
): number {
|
|
57
|
+
if (sortedDurations.length === 0) {
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const clampedRank = Math.max(0, Math.min(1, rank));
|
|
62
|
+
const index = Math.min(
|
|
63
|
+
sortedDurations.length - 1,
|
|
64
|
+
Math.floor(clampedRank * (sortedDurations.length - 1)),
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return sortedDurations[index];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Formats a compact percentile summary for one ascending-sorted duration collection.
|
|
72
|
+
*
|
|
73
|
+
* @param sortedDurationsMs - Ascending-sorted duration samples in milliseconds.
|
|
74
|
+
* @returns Human-readable summary string.
|
|
75
|
+
*/
|
|
76
|
+
export function formatDistribution(
|
|
77
|
+
sortedDurationsMs: readonly number[],
|
|
78
|
+
): string {
|
|
79
|
+
if (sortedDurationsMs.length === 0) {
|
|
80
|
+
return 'count=0';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return [
|
|
84
|
+
`count=${sortedDurationsMs.length.toLocaleString()}`,
|
|
85
|
+
`p50=${formatMs(percentile(sortedDurationsMs, 0.5))}`,
|
|
86
|
+
`p90=${formatMs(percentile(sortedDurationsMs, 0.9))}`,
|
|
87
|
+
`p99=${formatMs(percentile(sortedDurationsMs, 0.99))}`,
|
|
88
|
+
`max=${formatMs(sortedDurationsMs.at(-1) ?? 0)}`,
|
|
89
|
+
].join(', ');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Creates a stable lookup key for one process id.
|
|
94
|
+
*
|
|
95
|
+
* @param pid - Process identifier from the trace.
|
|
96
|
+
* @returns Stable process key when the id exists.
|
|
97
|
+
*/
|
|
98
|
+
export function createProcessKey(pid: number | undefined): string | undefined {
|
|
99
|
+
return typeof pid === 'number' ? `pid:${pid}` : undefined;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Creates a stable lookup key for one process/thread pair.
|
|
104
|
+
*
|
|
105
|
+
* @param pid - Process identifier from the trace.
|
|
106
|
+
* @param tid - Thread identifier from the trace.
|
|
107
|
+
* @returns Stable thread key when both ids exist.
|
|
108
|
+
*/
|
|
109
|
+
export function createThreadKey(
|
|
110
|
+
pid: number | undefined,
|
|
111
|
+
tid: number | undefined,
|
|
112
|
+
): string | undefined {
|
|
113
|
+
return typeof pid === 'number' && typeof tid === 'number'
|
|
114
|
+
? `pid:${pid}:tid:${tid}`
|
|
115
|
+
: undefined;
|
|
116
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads a Chrome or Perfetto trace export and prints a compact performance
|
|
3
|
+
* report.
|
|
4
|
+
*
|
|
5
|
+
* The entrypoint stays intentionally small: CLI parsing, trace loading,
|
|
6
|
+
* analysis, and report rendering each live in focused sibling modules.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npm run trace:analyze -- test/examples/flappy_bird/Trace-20260309T191949.json
|
|
10
|
+
* npm run docs:build-scripts && node dist-docs/scripts/analyze-trace/analyze-trace.js path/to/trace.json --top=20
|
|
11
|
+
*/
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
|
|
14
|
+
import { analyzeTraceEvents } from './analyze-trace.analysis.js';
|
|
15
|
+
import { loadTrace, resolveCliOptions } from './analyze-trace.io.js';
|
|
16
|
+
import { printTraceReport } from './analyze-trace.report.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* CLI entry point.
|
|
20
|
+
*
|
|
21
|
+
* @returns Nothing.
|
|
22
|
+
*/
|
|
23
|
+
function main(): void {
|
|
24
|
+
// Step 1: Resolve the CLI request and load the raw trace.
|
|
25
|
+
const cliOptions = resolveCliOptions(process.argv.slice(2));
|
|
26
|
+
const traceFilePath = path.resolve(cliOptions.tracePath);
|
|
27
|
+
const traceFile = loadTrace(traceFilePath);
|
|
28
|
+
const traceEvents = traceFile.traceEvents ?? [];
|
|
29
|
+
|
|
30
|
+
if (traceEvents.length === 0) {
|
|
31
|
+
throw new Error(`Trace contains no events: ${traceFilePath}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Step 2: Derive deterministic report data from the raw trace.
|
|
35
|
+
const traceAnalysis = analyzeTraceEvents({
|
|
36
|
+
traceFilePath,
|
|
37
|
+
traceEvents,
|
|
38
|
+
topCount: cliOptions.topCount,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Step 3: Render the final textual report.
|
|
42
|
+
printTraceReport(traceAnalysis);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
main();
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** Primitive trace metadata value supported by the nested args reader. */
|
|
2
|
+
export type Primitive = string | number | boolean | null | undefined;
|
|
3
|
+
|
|
4
|
+
/** Minimal Chrome or Perfetto trace event shape used by the analyzer. */
|
|
5
|
+
export interface TraceEvent {
|
|
6
|
+
pid?: number;
|
|
7
|
+
tid?: number;
|
|
8
|
+
ts?: number;
|
|
9
|
+
dur?: number;
|
|
10
|
+
tdur?: number;
|
|
11
|
+
ph?: string;
|
|
12
|
+
cat?: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
args?: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Top-level trace file shape expected from exported JSON captures. */
|
|
18
|
+
export interface TraceFile {
|
|
19
|
+
traceEvents?: TraceEvent[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Parsed CLI options for one analyzer invocation. */
|
|
23
|
+
export interface CliOptions {
|
|
24
|
+
tracePath: string;
|
|
25
|
+
topCount: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Summary metrics for one thread label in the trace. */
|
|
29
|
+
export interface ThreadSummary {
|
|
30
|
+
label: string;
|
|
31
|
+
totalDurationMs: number;
|
|
32
|
+
runTaskDurationMs: number;
|
|
33
|
+
longTaskCount16ms: number;
|
|
34
|
+
longTaskCount50ms: number;
|
|
35
|
+
maxTaskMs: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Aggregated duration rollup for one trace event or one script URL. */
|
|
39
|
+
export interface AggregatedDuration {
|
|
40
|
+
name: string;
|
|
41
|
+
count: number;
|
|
42
|
+
totalMs: number;
|
|
43
|
+
maxMs: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Longest single complete event entry used by the report. */
|
|
47
|
+
export interface LongEventSummary {
|
|
48
|
+
durationMs: number;
|
|
49
|
+
threadLabel: string;
|
|
50
|
+
eventName: string;
|
|
51
|
+
scriptUrl?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Visible trace window spanned by the capture. */
|
|
55
|
+
export interface TraceTimeRange {
|
|
56
|
+
windowMs: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Fully analyzed trace payload used by the reporting layer. */
|
|
60
|
+
export interface TraceAnalysis {
|
|
61
|
+
traceFilePath: string;
|
|
62
|
+
traceEventCount: number;
|
|
63
|
+
timeRange: TraceTimeRange;
|
|
64
|
+
droppedFrameCount: number;
|
|
65
|
+
beginFrameCount: number;
|
|
66
|
+
threadSummaries: ThreadSummary[];
|
|
67
|
+
hottestEvents: AggregatedDuration[];
|
|
68
|
+
hottestFunctionCalls: AggregatedDuration[];
|
|
69
|
+
longestEvents: LongEventSummary[];
|
|
70
|
+
fireAnimationFrameDurations: number[];
|
|
71
|
+
functionCallDurations: number[];
|
|
72
|
+
}
|
package/scripts/assets/theme.css
CHANGED
|
@@ -22,14 +22,11 @@
|
|
|
22
22
|
--double-border: 3px double rgba(15, 181, 255, 0.88);
|
|
23
23
|
--double-border-soft: 3px double rgba(10, 142, 160, 0.58);
|
|
24
24
|
--panel-glow:
|
|
25
|
-
inset 0 0 0 1px rgba(15, 181, 255, 0.16),
|
|
26
|
-
0 0 18px rgba(15, 181, 255, 0.12);
|
|
25
|
+
inset 0 0 0 1px rgba(15, 181, 255, 0.16), 0 0 18px rgba(15, 181, 255, 0.12);
|
|
27
26
|
--panel-glow-strong:
|
|
28
|
-
inset 0 0 0 1px rgba(15, 181, 255, 0.2),
|
|
29
|
-
0 0 24px rgba(0, 229, 255, 0.15);
|
|
27
|
+
inset 0 0 0 1px rgba(15, 181, 255, 0.2), 0 0 24px rgba(0, 229, 255, 0.15);
|
|
30
28
|
--focus-ring:
|
|
31
|
-
0 0 0 2px rgba(255, 154, 46, 0.9),
|
|
32
|
-
0 0 0 5px rgba(15, 181, 255, 0.2);
|
|
29
|
+
0 0 0 2px rgba(255, 154, 46, 0.9), 0 0 0 5px rgba(15, 181, 255, 0.2);
|
|
33
30
|
}
|
|
34
31
|
* {
|
|
35
32
|
box-sizing: border-box;
|
|
@@ -60,13 +57,35 @@ body::before {
|
|
|
60
57
|
inset: 0;
|
|
61
58
|
pointer-events: none;
|
|
62
59
|
background:
|
|
63
|
-
radial-gradient(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
radial-gradient(
|
|
61
|
+
circle at 12% 18%,
|
|
62
|
+
rgba(255, 255, 255, 0.2) 0 1px,
|
|
63
|
+
transparent 1.5px
|
|
64
|
+
),
|
|
65
|
+
radial-gradient(
|
|
66
|
+
circle at 78% 12%,
|
|
67
|
+
rgba(159, 220, 255, 0.18) 0 1px,
|
|
68
|
+
transparent 1.5px
|
|
69
|
+
),
|
|
70
|
+
radial-gradient(
|
|
71
|
+
circle at 68% 42%,
|
|
72
|
+
rgba(0, 229, 255, 0.14) 0 1px,
|
|
73
|
+
transparent 1.5px
|
|
74
|
+
),
|
|
75
|
+
radial-gradient(
|
|
76
|
+
circle at 28% 72%,
|
|
77
|
+
rgba(255, 255, 255, 0.12) 0 1px,
|
|
78
|
+
transparent 1.5px
|
|
79
|
+
),
|
|
67
80
|
linear-gradient(rgba(10, 142, 160, 0.05) 1px, transparent 1px),
|
|
68
81
|
linear-gradient(90deg, rgba(10, 142, 160, 0.04) 1px, transparent 1px);
|
|
69
|
-
background-size:
|
|
82
|
+
background-size:
|
|
83
|
+
auto,
|
|
84
|
+
auto,
|
|
85
|
+
auto,
|
|
86
|
+
auto,
|
|
87
|
+
100% 28px,
|
|
88
|
+
28px 100%;
|
|
70
89
|
opacity: 0.45;
|
|
71
90
|
z-index: -1;
|
|
72
91
|
}
|
|
@@ -89,8 +108,11 @@ a:focus-visible {
|
|
|
89
108
|
position: sticky;
|
|
90
109
|
top: 0;
|
|
91
110
|
z-index: 30;
|
|
92
|
-
background:
|
|
93
|
-
|
|
111
|
+
background: linear-gradient(
|
|
112
|
+
180deg,
|
|
113
|
+
rgba(0, 0, 0, 0.96),
|
|
114
|
+
rgba(3, 8, 18, 0.94)
|
|
115
|
+
);
|
|
94
116
|
backdrop-filter: blur(8px);
|
|
95
117
|
border-bottom: var(--double-border-soft);
|
|
96
118
|
box-shadow:
|
|
@@ -225,7 +247,11 @@ a:focus-visible {
|
|
|
225
247
|
max-height: calc(100vh - 90px);
|
|
226
248
|
overflow: auto;
|
|
227
249
|
background:
|
|
228
|
-
radial-gradient(
|
|
250
|
+
radial-gradient(
|
|
251
|
+
circle at top left,
|
|
252
|
+
rgba(0, 229, 255, 0.08),
|
|
253
|
+
transparent 36%
|
|
254
|
+
),
|
|
229
255
|
linear-gradient(180deg, rgba(3, 17, 31, 0.98), rgba(0, 0, 0, 0.98));
|
|
230
256
|
border: var(--double-border);
|
|
231
257
|
border-radius: 0;
|
|
@@ -281,14 +307,21 @@ a:focus-visible {
|
|
|
281
307
|
position: relative;
|
|
282
308
|
padding: 12px;
|
|
283
309
|
border: var(--double-border-soft);
|
|
284
|
-
background:
|
|
285
|
-
|
|
310
|
+
background: linear-gradient(
|
|
311
|
+
180deg,
|
|
312
|
+
rgba(3, 17, 31, 0.96),
|
|
313
|
+
rgba(0, 0, 0, 0.98)
|
|
314
|
+
);
|
|
286
315
|
box-shadow: var(--panel-glow);
|
|
287
316
|
}
|
|
288
317
|
.group-priority {
|
|
289
318
|
padding: 12px;
|
|
290
319
|
background:
|
|
291
|
-
radial-gradient(
|
|
320
|
+
radial-gradient(
|
|
321
|
+
circle at top left,
|
|
322
|
+
rgba(255, 154, 46, 0.08),
|
|
323
|
+
transparent 34%
|
|
324
|
+
),
|
|
292
325
|
linear-gradient(180deg, rgba(3, 17, 31, 0.98), rgba(0, 0, 0, 0.98));
|
|
293
326
|
border: var(--double-border);
|
|
294
327
|
box-shadow: var(--panel-glow-strong);
|
|
@@ -318,7 +351,11 @@ a:focus-visible {
|
|
|
318
351
|
border-radius: 0;
|
|
319
352
|
border: var(--double-border-soft);
|
|
320
353
|
background:
|
|
321
|
-
radial-gradient(
|
|
354
|
+
radial-gradient(
|
|
355
|
+
circle at top left,
|
|
356
|
+
rgba(0, 229, 255, 0.08),
|
|
357
|
+
transparent 40%
|
|
358
|
+
),
|
|
322
359
|
linear-gradient(180deg, rgba(3, 17, 31, 0.98), rgba(0, 0, 0, 0.98));
|
|
323
360
|
box-shadow: var(--panel-glow);
|
|
324
361
|
}
|
|
@@ -432,7 +469,11 @@ a:focus-visible {
|
|
|
432
469
|
bottom: -1px;
|
|
433
470
|
width: var(--pipe-rail-thickness);
|
|
434
471
|
transform: translateX(-50%);
|
|
435
|
-
background: linear-gradient(
|
|
472
|
+
background: linear-gradient(
|
|
473
|
+
180deg,
|
|
474
|
+
rgba(15, 181, 255, 0.94),
|
|
475
|
+
rgba(10, 142, 160, 0.78)
|
|
476
|
+
);
|
|
436
477
|
box-shadow: 0 0 8px rgba(0, 229, 255, 0.16);
|
|
437
478
|
transition:
|
|
438
479
|
background 120ms ease,
|
|
@@ -446,7 +487,11 @@ a:focus-visible {
|
|
|
446
487
|
top: 50%;
|
|
447
488
|
height: var(--pipe-rail-thickness);
|
|
448
489
|
transform: translateY(-50%);
|
|
449
|
-
background: linear-gradient(
|
|
490
|
+
background: linear-gradient(
|
|
491
|
+
90deg,
|
|
492
|
+
rgba(15, 181, 255, 0.94),
|
|
493
|
+
rgba(10, 142, 160, 0.78)
|
|
494
|
+
);
|
|
450
495
|
box-shadow: 0 0 8px rgba(0, 229, 255, 0.16);
|
|
451
496
|
transition:
|
|
452
497
|
background 120ms ease,
|
|
@@ -479,7 +524,11 @@ a:focus-visible {
|
|
|
479
524
|
.pipe-nav-item:hover .nav-rail-cell-last::after,
|
|
480
525
|
.pipe-nav-item.current .nav-rail-cell::before,
|
|
481
526
|
.pipe-nav-item.current .nav-rail-cell-last::after {
|
|
482
|
-
background: linear-gradient(
|
|
527
|
+
background: linear-gradient(
|
|
528
|
+
180deg,
|
|
529
|
+
rgba(255, 154, 46, 0.98),
|
|
530
|
+
rgba(255, 92, 255, 0.72)
|
|
531
|
+
);
|
|
483
532
|
box-shadow: 0 0 10px rgba(255, 154, 46, 0.22);
|
|
484
533
|
}
|
|
485
534
|
.pipe-nav-item:hover .nav-link-label,
|
|
@@ -631,7 +680,11 @@ table {
|
|
|
631
680
|
display: block;
|
|
632
681
|
overflow: auto;
|
|
633
682
|
border: var(--double-border-soft);
|
|
634
|
-
background: linear-gradient(
|
|
683
|
+
background: linear-gradient(
|
|
684
|
+
180deg,
|
|
685
|
+
rgba(3, 17, 31, 0.98),
|
|
686
|
+
rgba(0, 0, 0, 0.98)
|
|
687
|
+
);
|
|
635
688
|
box-shadow: var(--panel-glow);
|
|
636
689
|
}
|
|
637
690
|
th,
|
|
@@ -649,7 +702,11 @@ blockquote {
|
|
|
649
702
|
padding: 12px 14px;
|
|
650
703
|
border-left: 3px double var(--accent-orange);
|
|
651
704
|
background:
|
|
652
|
-
radial-gradient(
|
|
705
|
+
radial-gradient(
|
|
706
|
+
circle at top left,
|
|
707
|
+
rgba(255, 92, 255, 0.08),
|
|
708
|
+
transparent 36%
|
|
709
|
+
),
|
|
653
710
|
linear-gradient(180deg, rgba(12, 8, 24, 0.98), rgba(0, 0, 0, 0.98));
|
|
654
711
|
border-radius: 0;
|
|
655
712
|
box-shadow: var(--panel-glow);
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copies browser-viewable examples into docs/examples/* so GitHub Pages can
|
|
3
|
+
* publish them alongside the generated documentation site.
|
|
4
|
+
*
|
|
5
|
+
* The script intentionally keeps one narrow contract: copy each example's
|
|
6
|
+
* browser entrypoint into its published docs folder, then rebuild the shared
|
|
7
|
+
* examples landing page from the demos that were actually published.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { access, copyFile, mkdir, writeFile } from 'node:fs/promises';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
|
|
13
|
+
const DOCS_EXAMPLES_LOG_PREFIX = '[docs:examples]';
|
|
14
|
+
const DOCS_EXAMPLES_DIR = path.resolve('docs', 'examples');
|
|
15
|
+
const EXAMPLE_ENTRY_FILE_NAME = 'index.html';
|
|
16
|
+
const DOCS_THEME_STYLESHEET_PATH = '../assets/theme.css';
|
|
17
|
+
const DOCS_HOME_PATH = '../index.html';
|
|
18
|
+
const EXAMPLES_HOME_PATH = './index.html';
|
|
19
|
+
const GITHUB_REPOSITORY_URL = 'https://github.com/reicek/NeatapticTS';
|
|
20
|
+
|
|
21
|
+
interface ExampleDefinition {
|
|
22
|
+
dirName: string;
|
|
23
|
+
label: string;
|
|
24
|
+
title: string;
|
|
25
|
+
sourceDir: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface PublishedExample {
|
|
29
|
+
dirName: string;
|
|
30
|
+
label: string;
|
|
31
|
+
title: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const EXAMPLE_DEFINITIONS: readonly ExampleDefinition[] = [
|
|
35
|
+
{
|
|
36
|
+
dirName: 'asciiMaze',
|
|
37
|
+
label: 'asciiMaze',
|
|
38
|
+
title: 'ASCII Maze (NeatapticTS)',
|
|
39
|
+
sourceDir: path.resolve('test', 'examples', 'asciiMaze'),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
dirName: 'flappy_bird',
|
|
43
|
+
label: 'flappy_bird',
|
|
44
|
+
title: 'Flappy Bird (NeatapticTS)',
|
|
45
|
+
sourceDir: path.resolve('test', 'examples', 'flappy_bird'),
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Runs the example-copy workflow.
|
|
51
|
+
*
|
|
52
|
+
* Step 1 copies published browser entrypoints for all known examples.
|
|
53
|
+
* Step 2 rebuilds the landing page from the demos that were actually copied.
|
|
54
|
+
*
|
|
55
|
+
* @returns Promise resolved when copying and landing-page generation complete.
|
|
56
|
+
*/
|
|
57
|
+
async function main(): Promise<void> {
|
|
58
|
+
const publishedExamples = (
|
|
59
|
+
await Promise.all(EXAMPLE_DEFINITIONS.map(copyExampleEntryPoint))
|
|
60
|
+
).filter(isPublishedExample);
|
|
61
|
+
|
|
62
|
+
await writeExamplesLandingPage(publishedExamples);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Copies one example entrypoint into `docs/examples/<name>/index.html`.
|
|
67
|
+
*
|
|
68
|
+
* @param exampleDefinition - Example publishing definition.
|
|
69
|
+
* @returns Published example metadata when the example entrypoint was copied,
|
|
70
|
+
* otherwise `null`.
|
|
71
|
+
*/
|
|
72
|
+
async function copyExampleEntryPoint(
|
|
73
|
+
exampleDefinition: ExampleDefinition,
|
|
74
|
+
): Promise<PublishedExample | null> {
|
|
75
|
+
const hasSourceDirectory = await pathExists(exampleDefinition.sourceDir);
|
|
76
|
+
if (!hasSourceDirectory) {
|
|
77
|
+
console.warn(
|
|
78
|
+
`${DOCS_EXAMPLES_LOG_PREFIX} ${exampleDefinition.dirName} source directory not found, skipping`,
|
|
79
|
+
);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const sourceIndexPath = path.join(
|
|
84
|
+
exampleDefinition.sourceDir,
|
|
85
|
+
EXAMPLE_ENTRY_FILE_NAME,
|
|
86
|
+
);
|
|
87
|
+
const hasSourceIndex = await pathExists(sourceIndexPath);
|
|
88
|
+
if (!hasSourceIndex) {
|
|
89
|
+
console.warn(
|
|
90
|
+
`${DOCS_EXAMPLES_LOG_PREFIX} ${exampleDefinition.dirName} ${EXAMPLE_ENTRY_FILE_NAME} missing`,
|
|
91
|
+
);
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const destinationDirectoryPath = path.join(
|
|
96
|
+
DOCS_EXAMPLES_DIR,
|
|
97
|
+
exampleDefinition.dirName,
|
|
98
|
+
);
|
|
99
|
+
const destinationIndexPath = path.join(
|
|
100
|
+
destinationDirectoryPath,
|
|
101
|
+
EXAMPLE_ENTRY_FILE_NAME,
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
await mkdir(destinationDirectoryPath, { recursive: true });
|
|
105
|
+
await copyFile(sourceIndexPath, destinationIndexPath);
|
|
106
|
+
|
|
107
|
+
console.log(
|
|
108
|
+
`${DOCS_EXAMPLES_LOG_PREFIX} Copied ${exampleDefinition.dirName} ${EXAMPLE_ENTRY_FILE_NAME}`,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
dirName: exampleDefinition.dirName,
|
|
113
|
+
label: exampleDefinition.label,
|
|
114
|
+
title: exampleDefinition.title,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Writes the shared docs/examples landing page.
|
|
120
|
+
*
|
|
121
|
+
* @param publishedExamples - Examples that were published in the current run.
|
|
122
|
+
* @returns Promise resolved when the landing page has been written.
|
|
123
|
+
*/
|
|
124
|
+
async function writeExamplesLandingPage(
|
|
125
|
+
publishedExamples: readonly PublishedExample[],
|
|
126
|
+
): Promise<void> {
|
|
127
|
+
await mkdir(DOCS_EXAMPLES_DIR, { recursive: true });
|
|
128
|
+
|
|
129
|
+
const examplesLandingPageHtml =
|
|
130
|
+
buildExamplesLandingPageHtml(publishedExamples);
|
|
131
|
+
await writeFile(
|
|
132
|
+
path.join(DOCS_EXAMPLES_DIR, EXAMPLE_ENTRY_FILE_NAME),
|
|
133
|
+
examplesLandingPageHtml,
|
|
134
|
+
'utf8',
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
console.log(`${DOCS_EXAMPLES_LOG_PREFIX} Wrote examples landing page`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Builds the shared examples landing page HTML.
|
|
142
|
+
*
|
|
143
|
+
* @param publishedExamples - Examples that were published in the current run.
|
|
144
|
+
* @returns Rendered landing page HTML.
|
|
145
|
+
*/
|
|
146
|
+
function buildExamplesLandingPageHtml(
|
|
147
|
+
publishedExamples: readonly PublishedExample[],
|
|
148
|
+
): string {
|
|
149
|
+
const examplesListMarkup = buildExamplesListMarkup(publishedExamples);
|
|
150
|
+
|
|
151
|
+
return `<!doctype html>
|
|
152
|
+
<html lang="en">
|
|
153
|
+
<head>
|
|
154
|
+
<meta charset="utf-8" />
|
|
155
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
156
|
+
<title>Examples • NeatapticTS Docs</title>
|
|
157
|
+
<link rel="stylesheet" href="${DOCS_THEME_STYLESHEET_PATH}" />
|
|
158
|
+
</head>
|
|
159
|
+
<body>
|
|
160
|
+
<header class="topbar">
|
|
161
|
+
<div class="inner">
|
|
162
|
+
<div class="brand"><a href="${DOCS_HOME_PATH}">NeatapticTS</a></div>
|
|
163
|
+
<nav class="main-nav">
|
|
164
|
+
<a href="${DOCS_HOME_PATH}">Home</a>
|
|
165
|
+
<a href="${DOCS_HOME_PATH}">Docs</a>
|
|
166
|
+
<a href="${EXAMPLES_HOME_PATH}" class="active">Examples</a>
|
|
167
|
+
<a href="${GITHUB_REPOSITORY_URL}" target="_blank" rel="noopener">GitHub</a>
|
|
168
|
+
</nav>
|
|
169
|
+
</div>
|
|
170
|
+
</header>
|
|
171
|
+
<div class="layout">
|
|
172
|
+
<main class="content">
|
|
173
|
+
<h1>Examples</h1>
|
|
174
|
+
<p>Interactive browser demos built from this repository:</p>
|
|
175
|
+
${examplesListMarkup}
|
|
176
|
+
<footer class="site-footer">Generated from source JSDoc • <a href="${GITHUB_REPOSITORY_URL}">GitHub</a></footer>
|
|
177
|
+
</main>
|
|
178
|
+
</div>
|
|
179
|
+
</body>
|
|
180
|
+
</html>`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Builds the published examples list markup.
|
|
185
|
+
*
|
|
186
|
+
* @param publishedExamples - Examples that were published in the current run.
|
|
187
|
+
* @returns HTML list markup.
|
|
188
|
+
*/
|
|
189
|
+
function buildExamplesListMarkup(
|
|
190
|
+
publishedExamples: readonly PublishedExample[],
|
|
191
|
+
): string {
|
|
192
|
+
if (publishedExamples.length === 0) {
|
|
193
|
+
return '<p>No interactive examples were published in this run.</p>';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const listItemsMarkup = publishedExamples
|
|
197
|
+
.toSorted((leftExample, rightExample) =>
|
|
198
|
+
leftExample.title.localeCompare(rightExample.title),
|
|
199
|
+
)
|
|
200
|
+
.map(
|
|
201
|
+
(publishedExample) =>
|
|
202
|
+
`<li><a href="./${publishedExample.dirName}/${EXAMPLE_ENTRY_FILE_NAME}">${publishedExample.title}</a> <span class="demo-path">(examples/${publishedExample.label})</span></li>`,
|
|
203
|
+
)
|
|
204
|
+
.join('');
|
|
205
|
+
|
|
206
|
+
return `<ul>${listItemsMarkup}</ul>`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Resolves whether a filesystem path exists.
|
|
211
|
+
*
|
|
212
|
+
* @param targetPath - Filesystem path to check.
|
|
213
|
+
* @returns True when the path exists.
|
|
214
|
+
*/
|
|
215
|
+
async function pathExists(targetPath: string): Promise<boolean> {
|
|
216
|
+
try {
|
|
217
|
+
await access(targetPath);
|
|
218
|
+
return true;
|
|
219
|
+
} catch {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Narrows `Promise.all` output to the published example shape.
|
|
226
|
+
*
|
|
227
|
+
* @param publishedExample - Candidate example result.
|
|
228
|
+
* @returns `true` when the example was published successfully.
|
|
229
|
+
*/
|
|
230
|
+
function isPublishedExample(
|
|
231
|
+
publishedExample: PublishedExample | null,
|
|
232
|
+
): publishedExample is PublishedExample {
|
|
233
|
+
return publishedExample !== null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
main().catch((error: unknown) => {
|
|
237
|
+
console.error(`${DOCS_EXAMPLES_LOG_PREFIX} Failed:`, error);
|
|
238
|
+
process.exit(1);
|
|
239
|
+
});
|