@a14y/telemetry 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/core/types.d.ts +1 -1
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +6 -1
- package/dist/cjs/scorecard.d.ts +69 -0
- package/dist/cjs/scorecard.js +127 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/scorecard.js +121 -0
- package/package.json +1 -1
package/dist/cjs/core/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Adapter } from '../adapters/types';
|
|
2
2
|
export type AppName = 'cli' | 'extension' | 'docs';
|
|
3
|
-
export type EventName = 'cli_command_invoked' | 'cli_run_completed' | 'cli_error' | 'cli_telemetry_disabled' | 'ext_installed' | 'ext_audit_started' | 'ext_audit_completed' | 'ext_audit_error' | 'ext_settings_changed' | 'docs_section_view' | 'outbound_click';
|
|
3
|
+
export type EventName = 'cli_command_invoked' | 'cli_run_completed' | 'cli_error' | 'cli_telemetry_disabled' | 'ext_installed' | 'ext_audit_started' | 'ext_audit_completed' | 'ext_audit_error' | 'ext_settings_changed' | 'docs_section_view' | 'outbound_click' | 'scorecard_check_result';
|
|
4
4
|
export type EventParamValue = string | number | boolean;
|
|
5
5
|
export interface TelemetryEvent {
|
|
6
6
|
name: string;
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -5,3 +5,4 @@ export type { AppName, EventName, EventParamValue, TelemetryEvent, ConfigProvide
|
|
|
5
5
|
export { noopAdapter } from './adapters/noop';
|
|
6
6
|
export { createGa4MpAdapter, type Ga4MpAdapterOptions } from './adapters/ga4-mp';
|
|
7
7
|
export type { Adapter, AdapterPayload } from './adapters/types';
|
|
8
|
+
export { generateRunId, rollupPageStatuses, trackScorecardCheckResult, emitScorecardChecksFromRun, type ScorecardCheckStatus, type TelemetrySurface, type PageStatusRollup, type ScorecardCheckResultParams, type ScorecardRunLike, type EmitScorecardChecksFromRunOptions, } from './scorecard';
|
package/dist/cjs/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// Splitting them out keeps the extension bundle from pulling in `fs`/`os`
|
|
7
7
|
// and the Node consumers from pulling in the chrome.* type surface.
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.createGa4MpAdapter = exports.noopAdapter = exports.isValidEventName = exports.errorClassName = exports.sanitizeProps = exports.bucketDurationMs = exports.bucketIssueCount = exports.bucketPageCount = exports.bucketScore = exports.shutdown = exports.flush = exports.isEnabled = exports.setEnabled = exports.track = exports.init = void 0;
|
|
9
|
+
exports.emitScorecardChecksFromRun = exports.trackScorecardCheckResult = exports.rollupPageStatuses = exports.generateRunId = exports.createGa4MpAdapter = exports.noopAdapter = exports.isValidEventName = exports.errorClassName = exports.sanitizeProps = exports.bucketDurationMs = exports.bucketIssueCount = exports.bucketPageCount = exports.bucketScore = exports.shutdown = exports.flush = exports.isEnabled = exports.setEnabled = exports.track = exports.init = void 0;
|
|
10
10
|
var tracker_1 = require("./core/tracker");
|
|
11
11
|
Object.defineProperty(exports, "init", { enumerable: true, get: function () { return tracker_1.init; } });
|
|
12
12
|
Object.defineProperty(exports, "track", { enumerable: true, get: function () { return tracker_1.track; } });
|
|
@@ -27,3 +27,8 @@ var noop_1 = require("./adapters/noop");
|
|
|
27
27
|
Object.defineProperty(exports, "noopAdapter", { enumerable: true, get: function () { return noop_1.noopAdapter; } });
|
|
28
28
|
var ga4_mp_1 = require("./adapters/ga4-mp");
|
|
29
29
|
Object.defineProperty(exports, "createGa4MpAdapter", { enumerable: true, get: function () { return ga4_mp_1.createGa4MpAdapter; } });
|
|
30
|
+
var scorecard_1 = require("./scorecard");
|
|
31
|
+
Object.defineProperty(exports, "generateRunId", { enumerable: true, get: function () { return scorecard_1.generateRunId; } });
|
|
32
|
+
Object.defineProperty(exports, "rollupPageStatuses", { enumerable: true, get: function () { return scorecard_1.rollupPageStatuses; } });
|
|
33
|
+
Object.defineProperty(exports, "trackScorecardCheckResult", { enumerable: true, get: function () { return scorecard_1.trackScorecardCheckResult; } });
|
|
34
|
+
Object.defineProperty(exports, "emitScorecardChecksFromRun", { enumerable: true, get: function () { return scorecard_1.emitScorecardChecksFromRun; } });
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export type ScorecardCheckStatus = 'pass' | 'fail' | 'warn' | 'error' | 'na';
|
|
2
|
+
export type TelemetrySurface = 'cli' | 'ext';
|
|
3
|
+
/**
|
|
4
|
+
* Generate a per-run identifier. 8 hex chars (32 bits) is plenty — runs are
|
|
5
|
+
* scoped to a single GA4 property and at any realistic volume the collision
|
|
6
|
+
* probability inside a query window is negligible. We deliberately keep it
|
|
7
|
+
* short so the GA4 param-length budget stays generous for other dimensions.
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateRunId(): string;
|
|
10
|
+
export interface PageStatusRollup {
|
|
11
|
+
status: ScorecardCheckStatus;
|
|
12
|
+
failedPages: number;
|
|
13
|
+
totalPages: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Roll up a page-level check's per-page outcomes into one run-level outcome.
|
|
17
|
+
* Precedence is fail > error > warn > pass > na: any page failing wins, then
|
|
18
|
+
* any page erroring, etc. `na` only wins when every page returned `na`. The
|
|
19
|
+
* returned shape also exposes failed_pages / total_pages so analytics can
|
|
20
|
+
* distinguish "1 of 50 pages failed" from "all 50 failed".
|
|
21
|
+
*/
|
|
22
|
+
export declare function rollupPageStatuses(statuses: ScorecardCheckStatus[]): PageStatusRollup;
|
|
23
|
+
export interface ScorecardCheckResultParams {
|
|
24
|
+
runId: string;
|
|
25
|
+
checkId: string;
|
|
26
|
+
status: ScorecardCheckStatus;
|
|
27
|
+
scorecardVersion: string;
|
|
28
|
+
surface: TelemetrySurface;
|
|
29
|
+
/** Page-level checks: number of pages that returned `fail`. */
|
|
30
|
+
failedPages?: number;
|
|
31
|
+
/** Page-level checks: total number of pages this check ran against. */
|
|
32
|
+
totalPages?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Emit one `scorecard_check_result` event. Wraps the underlying tracker so
|
|
36
|
+
* callers don't reach for the GA4 event name directly and so the payload
|
|
37
|
+
* shape is type-checked.
|
|
38
|
+
*/
|
|
39
|
+
export declare function trackScorecardCheckResult(p: ScorecardCheckResultParams): void;
|
|
40
|
+
/**
|
|
41
|
+
* Duck-typed shape of a scorecard run. Defined locally so this package
|
|
42
|
+
* doesn't take a dependency on @a14y/core; callers pass the relevant slice
|
|
43
|
+
* of their own SiteRun. `status` accepts any string and is narrowed to a
|
|
44
|
+
* `ScorecardCheckStatus` at emit time.
|
|
45
|
+
*/
|
|
46
|
+
export interface ScorecardRunLike {
|
|
47
|
+
scorecardVersion: string;
|
|
48
|
+
siteChecks: ReadonlyArray<{
|
|
49
|
+
id: string;
|
|
50
|
+
status: string;
|
|
51
|
+
}>;
|
|
52
|
+
pages: ReadonlyArray<{
|
|
53
|
+
checks: ReadonlyArray<{
|
|
54
|
+
id: string;
|
|
55
|
+
status: string;
|
|
56
|
+
}>;
|
|
57
|
+
}>;
|
|
58
|
+
}
|
|
59
|
+
export interface EmitScorecardChecksFromRunOptions {
|
|
60
|
+
run: ScorecardRunLike;
|
|
61
|
+
runId: string;
|
|
62
|
+
surface: TelemetrySurface;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Emit one `scorecard_check_result` per stable check id in `run`. Site-level
|
|
66
|
+
* checks pass through their status verbatim; page-level checks are rolled up
|
|
67
|
+
* across pages. Returns the number of events emitted (mostly for tests).
|
|
68
|
+
*/
|
|
69
|
+
export declare function emitScorecardChecksFromRun(opts: EmitScorecardChecksFromRunOptions): number;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateRunId = generateRunId;
|
|
4
|
+
exports.rollupPageStatuses = rollupPageStatuses;
|
|
5
|
+
exports.trackScorecardCheckResult = trackScorecardCheckResult;
|
|
6
|
+
exports.emitScorecardChecksFromRun = emitScorecardChecksFromRun;
|
|
7
|
+
const tracker_1 = require("./core/tracker");
|
|
8
|
+
const HEX = '0123456789abcdef';
|
|
9
|
+
/**
|
|
10
|
+
* Generate a per-run identifier. 8 hex chars (32 bits) is plenty — runs are
|
|
11
|
+
* scoped to a single GA4 property and at any realistic volume the collision
|
|
12
|
+
* probability inside a query window is negligible. We deliberately keep it
|
|
13
|
+
* short so the GA4 param-length budget stays generous for other dimensions.
|
|
14
|
+
*/
|
|
15
|
+
function generateRunId() {
|
|
16
|
+
const bytes = new Uint8Array(4);
|
|
17
|
+
const g = globalThis;
|
|
18
|
+
if (g.crypto?.getRandomValues) {
|
|
19
|
+
g.crypto.getRandomValues(bytes);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
for (let i = 0; i < bytes.length; i++)
|
|
23
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
24
|
+
}
|
|
25
|
+
let out = '';
|
|
26
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
27
|
+
out += HEX[(bytes[i] >> 4) & 0xf] + HEX[bytes[i] & 0xf];
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Roll up a page-level check's per-page outcomes into one run-level outcome.
|
|
33
|
+
* Precedence is fail > error > warn > pass > na: any page failing wins, then
|
|
34
|
+
* any page erroring, etc. `na` only wins when every page returned `na`. The
|
|
35
|
+
* returned shape also exposes failed_pages / total_pages so analytics can
|
|
36
|
+
* distinguish "1 of 50 pages failed" from "all 50 failed".
|
|
37
|
+
*/
|
|
38
|
+
function rollupPageStatuses(statuses) {
|
|
39
|
+
let failed = 0;
|
|
40
|
+
let errored = 0;
|
|
41
|
+
let warned = 0;
|
|
42
|
+
let passed = 0;
|
|
43
|
+
for (const s of statuses) {
|
|
44
|
+
if (s === 'fail')
|
|
45
|
+
failed++;
|
|
46
|
+
else if (s === 'error')
|
|
47
|
+
errored++;
|
|
48
|
+
else if (s === 'warn')
|
|
49
|
+
warned++;
|
|
50
|
+
else if (s === 'pass')
|
|
51
|
+
passed++;
|
|
52
|
+
}
|
|
53
|
+
let status;
|
|
54
|
+
if (failed > 0)
|
|
55
|
+
status = 'fail';
|
|
56
|
+
else if (errored > 0)
|
|
57
|
+
status = 'error';
|
|
58
|
+
else if (warned > 0)
|
|
59
|
+
status = 'warn';
|
|
60
|
+
else if (passed > 0)
|
|
61
|
+
status = 'pass';
|
|
62
|
+
else
|
|
63
|
+
status = 'na';
|
|
64
|
+
return { status, failedPages: failed, totalPages: statuses.length };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Emit one `scorecard_check_result` event. Wraps the underlying tracker so
|
|
68
|
+
* callers don't reach for the GA4 event name directly and so the payload
|
|
69
|
+
* shape is type-checked.
|
|
70
|
+
*/
|
|
71
|
+
function trackScorecardCheckResult(p) {
|
|
72
|
+
const params = {
|
|
73
|
+
run_id: p.runId,
|
|
74
|
+
check_id: p.checkId,
|
|
75
|
+
status: p.status,
|
|
76
|
+
scorecard_version: p.scorecardVersion,
|
|
77
|
+
surface: p.surface,
|
|
78
|
+
};
|
|
79
|
+
if (typeof p.failedPages === 'number')
|
|
80
|
+
params.failed_pages = p.failedPages;
|
|
81
|
+
if (typeof p.totalPages === 'number')
|
|
82
|
+
params.total_pages = p.totalPages;
|
|
83
|
+
(0, tracker_1.track)('scorecard_check_result', params);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Emit one `scorecard_check_result` per stable check id in `run`. Site-level
|
|
87
|
+
* checks pass through their status verbatim; page-level checks are rolled up
|
|
88
|
+
* across pages. Returns the number of events emitted (mostly for tests).
|
|
89
|
+
*/
|
|
90
|
+
function emitScorecardChecksFromRun(opts) {
|
|
91
|
+
const { run, runId, surface } = opts;
|
|
92
|
+
let count = 0;
|
|
93
|
+
for (const check of run.siteChecks) {
|
|
94
|
+
trackScorecardCheckResult({
|
|
95
|
+
runId,
|
|
96
|
+
checkId: check.id,
|
|
97
|
+
status: check.status,
|
|
98
|
+
scorecardVersion: run.scorecardVersion,
|
|
99
|
+
surface,
|
|
100
|
+
});
|
|
101
|
+
count++;
|
|
102
|
+
}
|
|
103
|
+
const byCheckId = new Map();
|
|
104
|
+
for (const page of run.pages) {
|
|
105
|
+
for (const check of page.checks) {
|
|
106
|
+
const arr = byCheckId.get(check.id);
|
|
107
|
+
if (arr)
|
|
108
|
+
arr.push(check.status);
|
|
109
|
+
else
|
|
110
|
+
byCheckId.set(check.id, [check.status]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
for (const [checkId, statuses] of byCheckId) {
|
|
114
|
+
const rollup = rollupPageStatuses(statuses);
|
|
115
|
+
trackScorecardCheckResult({
|
|
116
|
+
runId,
|
|
117
|
+
checkId,
|
|
118
|
+
status: rollup.status,
|
|
119
|
+
scorecardVersion: run.scorecardVersion,
|
|
120
|
+
surface,
|
|
121
|
+
failedPages: rollup.failedPages,
|
|
122
|
+
totalPages: rollup.totalPages,
|
|
123
|
+
});
|
|
124
|
+
count++;
|
|
125
|
+
}
|
|
126
|
+
return count;
|
|
127
|
+
}
|
package/dist/esm/index.js
CHANGED
|
@@ -9,3 +9,4 @@ export { bucketScore, bucketPageCount, bucketIssueCount, bucketDurationMs, } fro
|
|
|
9
9
|
export { sanitizeProps, errorClassName, isValidEventName } from './core/sanitize';
|
|
10
10
|
export { noopAdapter } from './adapters/noop';
|
|
11
11
|
export { createGa4MpAdapter } from './adapters/ga4-mp';
|
|
12
|
+
export { generateRunId, rollupPageStatuses, trackScorecardCheckResult, emitScorecardChecksFromRun, } from './scorecard';
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { track } from './core/tracker';
|
|
2
|
+
const HEX = '0123456789abcdef';
|
|
3
|
+
/**
|
|
4
|
+
* Generate a per-run identifier. 8 hex chars (32 bits) is plenty — runs are
|
|
5
|
+
* scoped to a single GA4 property and at any realistic volume the collision
|
|
6
|
+
* probability inside a query window is negligible. We deliberately keep it
|
|
7
|
+
* short so the GA4 param-length budget stays generous for other dimensions.
|
|
8
|
+
*/
|
|
9
|
+
export function generateRunId() {
|
|
10
|
+
const bytes = new Uint8Array(4);
|
|
11
|
+
const g = globalThis;
|
|
12
|
+
if (g.crypto?.getRandomValues) {
|
|
13
|
+
g.crypto.getRandomValues(bytes);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
for (let i = 0; i < bytes.length; i++)
|
|
17
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
18
|
+
}
|
|
19
|
+
let out = '';
|
|
20
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
21
|
+
out += HEX[(bytes[i] >> 4) & 0xf] + HEX[bytes[i] & 0xf];
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Roll up a page-level check's per-page outcomes into one run-level outcome.
|
|
27
|
+
* Precedence is fail > error > warn > pass > na: any page failing wins, then
|
|
28
|
+
* any page erroring, etc. `na` only wins when every page returned `na`. The
|
|
29
|
+
* returned shape also exposes failed_pages / total_pages so analytics can
|
|
30
|
+
* distinguish "1 of 50 pages failed" from "all 50 failed".
|
|
31
|
+
*/
|
|
32
|
+
export function rollupPageStatuses(statuses) {
|
|
33
|
+
let failed = 0;
|
|
34
|
+
let errored = 0;
|
|
35
|
+
let warned = 0;
|
|
36
|
+
let passed = 0;
|
|
37
|
+
for (const s of statuses) {
|
|
38
|
+
if (s === 'fail')
|
|
39
|
+
failed++;
|
|
40
|
+
else if (s === 'error')
|
|
41
|
+
errored++;
|
|
42
|
+
else if (s === 'warn')
|
|
43
|
+
warned++;
|
|
44
|
+
else if (s === 'pass')
|
|
45
|
+
passed++;
|
|
46
|
+
}
|
|
47
|
+
let status;
|
|
48
|
+
if (failed > 0)
|
|
49
|
+
status = 'fail';
|
|
50
|
+
else if (errored > 0)
|
|
51
|
+
status = 'error';
|
|
52
|
+
else if (warned > 0)
|
|
53
|
+
status = 'warn';
|
|
54
|
+
else if (passed > 0)
|
|
55
|
+
status = 'pass';
|
|
56
|
+
else
|
|
57
|
+
status = 'na';
|
|
58
|
+
return { status, failedPages: failed, totalPages: statuses.length };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Emit one `scorecard_check_result` event. Wraps the underlying tracker so
|
|
62
|
+
* callers don't reach for the GA4 event name directly and so the payload
|
|
63
|
+
* shape is type-checked.
|
|
64
|
+
*/
|
|
65
|
+
export function trackScorecardCheckResult(p) {
|
|
66
|
+
const params = {
|
|
67
|
+
run_id: p.runId,
|
|
68
|
+
check_id: p.checkId,
|
|
69
|
+
status: p.status,
|
|
70
|
+
scorecard_version: p.scorecardVersion,
|
|
71
|
+
surface: p.surface,
|
|
72
|
+
};
|
|
73
|
+
if (typeof p.failedPages === 'number')
|
|
74
|
+
params.failed_pages = p.failedPages;
|
|
75
|
+
if (typeof p.totalPages === 'number')
|
|
76
|
+
params.total_pages = p.totalPages;
|
|
77
|
+
track('scorecard_check_result', params);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Emit one `scorecard_check_result` per stable check id in `run`. Site-level
|
|
81
|
+
* checks pass through their status verbatim; page-level checks are rolled up
|
|
82
|
+
* across pages. Returns the number of events emitted (mostly for tests).
|
|
83
|
+
*/
|
|
84
|
+
export function emitScorecardChecksFromRun(opts) {
|
|
85
|
+
const { run, runId, surface } = opts;
|
|
86
|
+
let count = 0;
|
|
87
|
+
for (const check of run.siteChecks) {
|
|
88
|
+
trackScorecardCheckResult({
|
|
89
|
+
runId,
|
|
90
|
+
checkId: check.id,
|
|
91
|
+
status: check.status,
|
|
92
|
+
scorecardVersion: run.scorecardVersion,
|
|
93
|
+
surface,
|
|
94
|
+
});
|
|
95
|
+
count++;
|
|
96
|
+
}
|
|
97
|
+
const byCheckId = new Map();
|
|
98
|
+
for (const page of run.pages) {
|
|
99
|
+
for (const check of page.checks) {
|
|
100
|
+
const arr = byCheckId.get(check.id);
|
|
101
|
+
if (arr)
|
|
102
|
+
arr.push(check.status);
|
|
103
|
+
else
|
|
104
|
+
byCheckId.set(check.id, [check.status]);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
for (const [checkId, statuses] of byCheckId) {
|
|
108
|
+
const rollup = rollupPageStatuses(statuses);
|
|
109
|
+
trackScorecardCheckResult({
|
|
110
|
+
runId,
|
|
111
|
+
checkId,
|
|
112
|
+
status: rollup.status,
|
|
113
|
+
scorecardVersion: run.scorecardVersion,
|
|
114
|
+
surface,
|
|
115
|
+
failedPages: rollup.failedPages,
|
|
116
|
+
totalPages: rollup.totalPages,
|
|
117
|
+
});
|
|
118
|
+
count++;
|
|
119
|
+
}
|
|
120
|
+
return count;
|
|
121
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a14y/telemetry",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Anonymous, opt-out telemetry shim shared by the a14y CLI and Chrome extension. Provider-agnostic core with a built-in GA4 Measurement Protocol adapter.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|