@electron-stagewright/plugin-budget 0.0.0-stage → 0.2.0

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 (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +214 -2
  3. package/dist/budget.d.ts +143 -0
  4. package/dist/budget.d.ts.map +1 -0
  5. package/dist/budget.js +134 -0
  6. package/dist/budget.js.map +1 -0
  7. package/dist/bundle.d.ts +15 -0
  8. package/dist/bundle.d.ts.map +1 -0
  9. package/dist/bundle.js +64 -0
  10. package/dist/bundle.js.map +1 -0
  11. package/dist/check-api.d.ts +15 -0
  12. package/dist/check-api.d.ts.map +1 -0
  13. package/dist/check-api.js +11 -0
  14. package/dist/check-api.js.map +1 -0
  15. package/dist/check.d.ts +50 -0
  16. package/dist/check.d.ts.map +1 -0
  17. package/dist/check.js +198 -0
  18. package/dist/check.js.map +1 -0
  19. package/dist/cli.d.ts +85 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +464 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/index.d.ts +24 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +17 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/measure.d.ts +81 -0
  28. package/dist/measure.d.ts.map +1 -0
  29. package/dist/measure.js +269 -0
  30. package/dist/measure.js.map +1 -0
  31. package/dist/memory.d.ts +43 -0
  32. package/dist/memory.d.ts.map +1 -0
  33. package/dist/memory.js +159 -0
  34. package/dist/memory.js.map +1 -0
  35. package/dist/plugin.d.ts +13 -0
  36. package/dist/plugin.d.ts.map +1 -0
  37. package/dist/plugin.js +456 -0
  38. package/dist/plugin.js.map +1 -0
  39. package/dist/probe.d.ts +74 -0
  40. package/dist/probe.d.ts.map +1 -0
  41. package/dist/probe.js +181 -0
  42. package/dist/probe.js.map +1 -0
  43. package/dist/render.d.ts +21 -0
  44. package/dist/render.d.ts.map +1 -0
  45. package/dist/render.js +63 -0
  46. package/dist/render.js.map +1 -0
  47. package/dist/run.d.ts +267 -0
  48. package/dist/run.d.ts.map +1 -0
  49. package/dist/run.js +257 -0
  50. package/dist/run.js.map +1 -0
  51. package/dist/session.d.ts +79 -0
  52. package/dist/session.d.ts.map +1 -0
  53. package/dist/session.js +263 -0
  54. package/dist/session.js.map +1 -0
  55. package/package.json +67 -3
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `@electron-stagewright/plugin-budget/check`: the budget and run formats and the check, without
3
+ * core, the plugin, or anything that launches Electron.
4
+ *
5
+ * @module
6
+ */
7
+ export { BUDGET_PLATFORMS, BudgetFileError, MEMORY_METRICS, PHASES, PROCESS_TYPES, budgetSchema, loadBudget, parseBudget, } from './budget.js';
8
+ export { checkRun } from './check.js';
9
+ export { compareRuns, renderCheckReport, renderComparison } from './render.js';
10
+ export { RUN_FORMAT, RUN_SCHEMA_VERSION, RunFileError, createRun, loadRun, memoryByType, mergeRuns, runSchema, summarizeLatencies, summarizeRun, } from './run.js';
11
+ //# sourceMappingURL=check-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-api.js","sourceRoot":"","sources":["../src/check-api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,MAAM,EACN,aAAa,EACb,YAAY,EACZ,UAAU,EACV,WAAW,GACZ,MAAM,aAAa,CAAA;AAUpB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE9E,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,OAAO,EACP,YAAY,EACZ,SAAS,EACT,SAAS,EACT,kBAAkB,EAClB,YAAY,GACb,MAAM,UAAU,CAAA"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Compare a run to a budget. Pure: no I/O, no Electron.
3
+ *
4
+ * @module
5
+ */
6
+ import { type Budget, type Phase } from './budget.js';
7
+ import { type BudgetRun, type SummaryRow } from './run.js';
8
+ export type CheckStatus = 'pass' | 'fail' | 'unmeasured';
9
+ export interface CheckResult {
10
+ readonly id: string;
11
+ readonly status: CheckStatus;
12
+ readonly unit: SummaryRow['unit'];
13
+ readonly limit: number;
14
+ /** `limit` plus the tolerance; the value that actually gates. */
15
+ readonly allowed: number;
16
+ readonly actual?: number;
17
+ readonly phase?: Phase;
18
+ readonly metric?: string;
19
+ /** Why it is unmeasured. */
20
+ readonly detail?: string;
21
+ }
22
+ export interface CheckReport {
23
+ /** False on any failure, and always false when nothing at all was measured. */
24
+ readonly passed: boolean;
25
+ readonly reason?: 'NO_EXPECTATIONS' | 'NO_MEASUREMENTS' | 'UNMEASURED' | 'OVER_BUDGET';
26
+ readonly summary: {
27
+ readonly pass: number;
28
+ readonly fail: number;
29
+ readonly unmeasured: number;
30
+ };
31
+ readonly results: readonly CheckResult[];
32
+ }
33
+ export interface CheckOptions {
34
+ /** Ignore every `thresholdPercent`: the limit itself gates. */
35
+ readonly ignoreThreshold?: boolean;
36
+ /** @deprecated Same as `ignoreThreshold`; it never meant "fail instead of warn". */
37
+ readonly strict?: boolean;
38
+ /** Treat a budgeted metric the run did not measure as a failure. */
39
+ readonly requireMeasurement?: boolean;
40
+ /** Read every metric from this phase instead of the budget's own phases. */
41
+ readonly phase?: Phase;
42
+ /**
43
+ * Rounds a runtime metric needs before its median counts; fewer leaves it `unmeasured`. Use it
44
+ * with `--rounds N` so that a median never rests on one launch. Bundle entries are exempt.
45
+ */
46
+ readonly minSamples?: number;
47
+ }
48
+ /** Compare `run` to `budget` for the platform the run was measured on. */
49
+ export declare function checkRun(run: BudgetRun, budget: Budget, options?: CheckOptions): CheckReport;
50
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAiB,KAAK,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,EAAgB,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAExE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,CAAA;AAExD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAA;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,4BAA4B;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,GAAG,YAAY,GAAG,aAAa,CAAA;IACtF,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/F,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAA;CACzC;AAED,MAAM,WAAW,YAAY;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;IAClC,oFAAoF;IACpF,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB,oEAAoE;IACpE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;IACrC,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAA;IACtB;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAuKD,0EAA0E;AAC1E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,WAAW,CAuDhG"}
package/dist/check.js ADDED
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Compare a run to a budget. Pure: no I/O, no Electron.
3
+ *
4
+ * @module
5
+ */
6
+ import { PROCESS_TYPES } from './budget.js';
7
+ import { summarizeRun } from './run.js';
8
+ const ANY_PHASE_ORDER = ['warm', 'live', 'cold'];
9
+ function expectations(budget, run, options) {
10
+ const platform = run.platform;
11
+ const list = [];
12
+ const tolerance = (own) => options.ignoreThreshold === true || options.strict === true
13
+ ? 0
14
+ : (own ?? budget.thresholdPercent ?? 0);
15
+ if (budget.startup !== undefined) {
16
+ list.push({
17
+ id: 'startup.firstWindowMs',
18
+ section: 'startup',
19
+ unit: 'ms',
20
+ limit: budget.startup.maxFirstWindowMs,
21
+ thresholdPercent: tolerance(budget.startup.thresholdPercent),
22
+ phase: options.phase ?? budget.startup.phase ?? 'cold',
23
+ });
24
+ }
25
+ const memory = budget.memory?.[platform];
26
+ if (memory !== undefined) {
27
+ const prefix = memory.aggregate === 'peak' ? 'memoryPeak' : 'memory';
28
+ // Unset: the first of warm, live, cold whose rounds measured memory, else that has rounds.
29
+ const roundsOf = (measured) => ANY_PHASE_ORDER.find((phase) => run.rounds.some((round) => round.phase === phase && (!measured || round.measurement[prefix] !== undefined)));
30
+ const memoryPhase = options.phase ?? memory.phase ?? roundsOf(true) ?? roundsOf(false);
31
+ const base = {
32
+ section: 'memory',
33
+ unit: 'MB',
34
+ thresholdPercent: tolerance(memory.thresholdPercent),
35
+ ...(memoryPhase === undefined ? {} : { phase: memoryPhase }),
36
+ metric: memory.metric,
37
+ };
38
+ for (const type of PROCESS_TYPES) {
39
+ const max = memory.perTypeMb?.[type];
40
+ if (max !== undefined)
41
+ list.push({ ...base, id: `${prefix}.${type}`, limit: max });
42
+ }
43
+ if (memory.totalWithoutGpuMb !== undefined) {
44
+ list.push({ ...base, id: `${prefix}.totalWithoutGpu`, limit: memory.totalWithoutGpuMb });
45
+ }
46
+ if (memory.totalMb !== undefined) {
47
+ list.push({ ...base, id: `${prefix}.total`, limit: memory.totalMb });
48
+ }
49
+ }
50
+ const mainThread = budget.mainThread;
51
+ if (mainThread !== undefined) {
52
+ const base = {
53
+ section: 'mainThread',
54
+ thresholdPercent: tolerance(mainThread.thresholdPercent),
55
+ ...(options.phase === undefined ? {} : { phase: options.phase }),
56
+ };
57
+ if (mainThread.maxBlockedPercent !== undefined) {
58
+ list.push({
59
+ ...base,
60
+ id: 'mainThread.blockedPercent',
61
+ unit: '%',
62
+ limit: mainThread.maxBlockedPercent,
63
+ });
64
+ }
65
+ if (mainThread.maxStallMs !== undefined) {
66
+ list.push({ ...base, id: 'mainThread.maxStallMs', unit: 'ms', limit: mainThread.maxStallMs });
67
+ }
68
+ }
69
+ const ipc = budget.ipc;
70
+ if (ipc !== undefined) {
71
+ const base = {
72
+ section: 'ipc',
73
+ unit: 'ms',
74
+ thresholdPercent: tolerance(ipc.thresholdPercent),
75
+ ...(options.phase === undefined ? {} : { phase: options.phase }),
76
+ };
77
+ if (ipc.maxP95Ms !== undefined)
78
+ list.push({ ...base, id: 'ipc.p95Ms', limit: ipc.maxP95Ms });
79
+ if (ipc.maxP99Ms !== undefined)
80
+ list.push({ ...base, id: 'ipc.p99Ms', limit: ipc.maxP99Ms });
81
+ }
82
+ for (const entry of budget.bundle?.entries ?? []) {
83
+ list.push({
84
+ id: `bundle.${entry.name ?? entry.path}`,
85
+ section: 'bundle',
86
+ unit: 'KB',
87
+ limit: entry.maxKb,
88
+ thresholdPercent: tolerance(budget.bundle?.thresholdPercent),
89
+ });
90
+ }
91
+ return list;
92
+ }
93
+ function findRow(rows, expectation) {
94
+ const candidates = rows.filter((row) => row.id === expectation.id &&
95
+ (expectation.metric === undefined || row.metric === expectation.metric));
96
+ if (expectation.section === 'bundle')
97
+ return candidates[0];
98
+ if (expectation.phase !== undefined) {
99
+ return candidates.find((row) => row.phase === expectation.phase);
100
+ }
101
+ for (const phase of ANY_PHASE_ORDER) {
102
+ const row = candidates.find((candidate) => candidate.phase === phase);
103
+ if (row !== undefined)
104
+ return row;
105
+ }
106
+ return undefined;
107
+ }
108
+ function unmeasuredDetail(run, expectation) {
109
+ if (expectation.section === 'bundle') {
110
+ const id = expectation.id.slice('bundle.'.length);
111
+ const entry = run.bundle?.entries.find((candidate) => candidate.id === id);
112
+ return entry?.unavailable ?? 'the run has no measurement for this bundle entry';
113
+ }
114
+ const rounds = run.rounds.filter((round) => expectation.phase === undefined || round.phase === expectation.phase);
115
+ if (rounds.length === 0) {
116
+ return expectation.phase === undefined
117
+ ? 'the run has no rounds'
118
+ : `the run has no ${expectation.phase} round`;
119
+ }
120
+ if (expectation.section === 'memory' &&
121
+ expectation.id.startsWith('memoryPeak.') &&
122
+ rounds.every((round) => round.measurement.memoryPeak === undefined) &&
123
+ rounds.some((round) => round.measurement.memory !== undefined)) {
124
+ const failed = rounds
125
+ .map((round) => round.measurement.unavailable?.['memoryPeak'])
126
+ .find((value) => value !== undefined);
127
+ return failed ?? 'the run has no peak sample; measure with --memory-sample-ms';
128
+ }
129
+ if (expectation.section === 'memory') {
130
+ const measured = rounds.map((round) => round.measurement.memory?.metric).find(Boolean);
131
+ // Megabytes in another metric are a different quantity, never a comparable one.
132
+ if (measured !== undefined && measured !== expectation.metric) {
133
+ return `the run measured ${measured}, the budget names ${expectation.metric}`;
134
+ }
135
+ }
136
+ if (expectation.section === 'ipc' && rounds.some((r) => r.measurement.ipc?.count === 0)) {
137
+ return 'the IPC probe completed no round trip';
138
+ }
139
+ const reason = rounds
140
+ .map((round) => round.measurement.unavailable?.[expectation.section])
141
+ .find((value) => value !== undefined);
142
+ return reason ?? `the run did not measure ${expectation.id}`;
143
+ }
144
+ /** Compare `run` to `budget` for the platform the run was measured on. */
145
+ export function checkRun(run, budget, options = {}) {
146
+ const rows = summarizeRun(run);
147
+ const results = expectations(budget, run, options).map((expectation) => {
148
+ // Divide last: 200 * (1 + 15 / 100) is 229.99999999999997, which would fail a 230.
149
+ const exactAllowed = (expectation.limit * (100 + expectation.thresholdPercent)) / 100;
150
+ const allowed = Math.round(exactAllowed * 10) / 10;
151
+ const base = {
152
+ id: expectation.id,
153
+ unit: expectation.unit,
154
+ limit: expectation.limit,
155
+ allowed,
156
+ ...(expectation.phase === undefined ? {} : { phase: expectation.phase }),
157
+ ...(expectation.metric === undefined ? {} : { metric: expectation.metric }),
158
+ };
159
+ const row = findRow(rows, expectation);
160
+ if (row === undefined) {
161
+ return { ...base, status: 'unmeasured', detail: unmeasuredDetail(run, expectation) };
162
+ }
163
+ const needed = options.minSamples ?? 1;
164
+ if (expectation.section !== 'bundle' && row.samples < needed) {
165
+ return {
166
+ ...base,
167
+ ...(row.phase === undefined ? {} : { phase: row.phase }),
168
+ status: 'unmeasured',
169
+ actual: row.value,
170
+ detail: `${row.samples} of the ${needed} rounds needed measured ${expectation.id}`,
171
+ };
172
+ }
173
+ return {
174
+ ...base,
175
+ ...(row.phase === undefined ? {} : { phase: row.phase }),
176
+ status: row.exact <= exactAllowed ? 'pass' : 'fail',
177
+ actual: row.value,
178
+ };
179
+ });
180
+ const count = (status) => results.filter((result) => result.status === status).length;
181
+ const summary = { pass: count('pass'), fail: count('fail'), unmeasured: count('unmeasured') };
182
+ const reason = results.length === 0
183
+ ? 'NO_EXPECTATIONS'
184
+ : summary.fail > 0
185
+ ? 'OVER_BUDGET'
186
+ : summary.pass === 0
187
+ ? 'NO_MEASUREMENTS'
188
+ : options.requireMeasurement === true && summary.unmeasured > 0
189
+ ? 'UNMEASURED'
190
+ : undefined;
191
+ return {
192
+ passed: reason === undefined,
193
+ ...(reason === undefined ? {} : { reason }),
194
+ summary,
195
+ results,
196
+ };
197
+ }
198
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `electron-stagewright-budget`: the CI face of the budget plugin.
4
+ *
5
+ * Exit codes: 0 within budget, 1 over budget or nothing measured, 2 usage, unreadable input, or any
6
+ * other error.
7
+ *
8
+ * @module
9
+ */
10
+ import { type Phase } from './budget.js';
11
+ import { measureApp, type LaunchPhase } from './measure.js';
12
+ export declare const BUDGET_EXIT_CODES: {
13
+ readonly SUCCESS: 0;
14
+ readonly OVER_BUDGET: 1;
15
+ readonly USAGE: 2;
16
+ };
17
+ export type BudgetExitCode = (typeof BUDGET_EXIT_CODES)[keyof typeof BUDGET_EXIT_CODES];
18
+ export interface BudgetCliIo {
19
+ readonly stdout: (text: string) => void;
20
+ readonly stderr: (text: string) => void;
21
+ }
22
+ export type BudgetCliOptions = {
23
+ readonly command: 'help';
24
+ } | {
25
+ readonly command: 'check';
26
+ readonly runPaths: readonly string[];
27
+ readonly budgetPath: string;
28
+ readonly noTolerance: boolean;
29
+ readonly minSamples?: number;
30
+ readonly requireMeasurement: boolean;
31
+ readonly phase?: Phase;
32
+ readonly json: boolean;
33
+ readonly deprecatedStrict?: true;
34
+ } | {
35
+ readonly command: 'compare';
36
+ readonly beforePath: string;
37
+ readonly afterPath: string;
38
+ readonly json: boolean;
39
+ } | {
40
+ readonly command: 'bundle';
41
+ readonly budgetPath: string;
42
+ readonly root?: string;
43
+ readonly outPath?: string;
44
+ readonly noTolerance: boolean;
45
+ readonly json: boolean;
46
+ readonly deprecatedStrict?: true;
47
+ } | MeasureCliOptions;
48
+ export interface MeasureCliOptions {
49
+ readonly command: 'measure';
50
+ readonly main?: string;
51
+ readonly executablePath?: string;
52
+ readonly args: readonly string[];
53
+ readonly env: Readonly<Record<string, string>>;
54
+ readonly budgetPath?: string;
55
+ readonly rounds: number;
56
+ readonly phases: readonly LaunchPhase[];
57
+ readonly settleMs?: number;
58
+ readonly windowMs?: number;
59
+ readonly workloadPath?: string;
60
+ readonly workloadTimeoutMs?: number;
61
+ readonly beforeRoundPath?: string;
62
+ readonly memorySampleMs?: number;
63
+ readonly skipFailedRounds: boolean;
64
+ readonly minSamples?: number;
65
+ readonly phase?: Phase;
66
+ readonly label?: string;
67
+ readonly outPath?: string;
68
+ readonly check: boolean;
69
+ readonly noTolerance: boolean;
70
+ readonly requireMeasurement: boolean;
71
+ readonly json: boolean;
72
+ readonly deprecatedStrict?: true;
73
+ }
74
+ /** Seam for tests: the launch-and-measure step. */
75
+ export interface BudgetCliDependencies {
76
+ readonly measureApp: typeof measureApp;
77
+ }
78
+ export declare function formatBudgetCliHelp(): string;
79
+ /** Strict parser: an unknown flag or a missing value is a usage error. */
80
+ export declare function parseBudgetCliArgs(argv: readonly string[]): BudgetCliOptions;
81
+ /** Execute already-parsed options. Throws the typed file errors; the caller maps them to exit 2. */
82
+ export declare function runBudgetCli(options: BudgetCliOptions, io?: BudgetCliIo, deps?: BudgetCliDependencies): Promise<BudgetExitCode>;
83
+ /** Parse and execute; never throws. */
84
+ export declare function runBudgetCliCommand(argv: readonly string[], io?: BudgetCliIo, deps?: BudgetCliDependencies): Promise<BudgetExitCode>;
85
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}