Skip to content

Commit ca99674

Browse files
committed
Normalize ConnectionThresholds field names
Rename downlink2gUpperBound/downlink3gUpperBound/downlink4gUpperBound to lowUpperBound/midUpperBound/highUpperBound, matching the pattern used by CpuThresholds and MemoryThresholds.
1 parent 863037c commit ca99674

9 files changed

Lines changed: 42 additions & 46 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Breaking Changes
66

7+
- **Normalize `ConnectionThresholds` field names** — Renamed `downlink2gUpperBound``lowUpperBound`, `downlink3gUpperBound``midUpperBound`, `downlink4gUpperBound``highUpperBound` to match the `CpuThresholds`/`MemoryThresholds` naming pattern. Update any custom `connection` threshold objects in your `thresholds` config
78
- **Rename `ConnectionTier` value `'fast'``'high'`** — Aligns connection tier vocabulary with CPU, memory, and GPU tiers which all use `'low' | 'mid' | 'high'`. Update any code comparing `tiers.connection === 'fast'` to use `'high'` instead
89
- **`classify()` and `deriveHints()` now accept `StoredSignals` instead of `RawSignals`** — These functions never used `userAgent` or `viewport` (which are stripped before storage). The narrower type makes the API honest. Existing call sites are unaffected — `RawSignals` is structurally assignable to `StoredSignals`
910
- **`profile:store` event now carries `StoredSignals` instead of `RawSignals`** — The event previously emitted the raw probe payload (including `userAgent`/`viewport`), not what was actually stored. The `signals` field now matches the persisted data. `bot:reject` still carries `RawSignals` (it fires before stripping)

docs/api/types.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ Validates custom tier thresholds after merging with defaults. Throws a descripti
5454
**Validation rules:**
5555

5656
- **CPU/Memory**: `lowUpperBound` must be less than `midUpperBound`
57-
- **Connection**: `downlink2gUpperBound` < `downlink3gUpperBound` < `downlink4gUpperBound`
57+
- **Connection**: `lowUpperBound` < `midUpperBound` < `highUpperBound`
5858
- **GPU**: `softwarePattern` and `highEndPattern` must be `RegExp` instances
5959
- All numeric values must be positive (> 0)
6060

@@ -156,11 +156,11 @@ Custom thresholds for tier classification. All fields are optional — unset fie
156156

157157
### ConnectionThresholds
158158

159-
| Field | Type | Default | Description |
160-
| ---------------------- | -------- | ------- | ------------------------------ |
161-
| `downlink2gUpperBound` | `number` | `0.5` | Mbps at or below → `'2g'` tier |
162-
| `downlink3gUpperBound` | `number` | `2` | Mbps at or below → `'3g'` tier |
163-
| `downlink4gUpperBound` | `number` | `5` | Mbps at or below → `'4g'` tier |
159+
| Field | Type | Default | Description |
160+
| ---------------- | -------- | ------- | ------------------------------ |
161+
| `lowUpperBound` | `number` | `0.5` | Mbps at or below → `'2g'` tier |
162+
| `midUpperBound` | `number` | `2` | Mbps at or below → `'3g'` tier |
163+
| `highUpperBound` | `number` | `5` | Mbps at or below → `'4g'` tier |
164164

165165
### GpuThresholds
166166

@@ -177,7 +177,7 @@ import { classify } from '@device-router/types';
177177
const tiers = classify(signals, {
178178
cpu: { lowUpperBound: 4, midUpperBound: 8 },
179179
memory: { midUpperBound: 8 },
180-
connection: { downlink4gUpperBound: 10 },
180+
connection: { highUpperBound: 10 },
181181
gpu: { highEndPattern: /\bRTX\b|\bGTX\b/i },
182182
});
183183
```

docs/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ const { middleware, probeEndpoint } = createDeviceRouter({
252252
thresholds: {
253253
cpu: { lowUpperBound: 4, midUpperBound: 8 },
254254
memory: { midUpperBound: 8 },
255-
connection: { downlink4gUpperBound: 10 },
255+
connection: { highUpperBound: 10 },
256256
},
257257
});
258258
```

packages/types/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ import { classify } from '@device-router/types';
6464
const tiers = classify(signals, {
6565
cpu: { lowUpperBound: 4, midUpperBound: 8 },
6666
memory: { midUpperBound: 8 },
67-
connection: { downlink4gUpperBound: 10 },
67+
connection: { highUpperBound: 10 },
6868
gpu: { highEndPattern: /\bRTX\b|\bGTX\b/i },
6969
});
7070
```

packages/types/src/__tests__/classify.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,18 +93,18 @@ describe('classifyConnection', () => {
9393

9494
it('uses custom downlink thresholds', () => {
9595
// With wider 2g band (up to 1 Mbps)
96-
expect(classifyConnection(undefined, 0.8, { downlink2gUpperBound: 1 })).toBe('2g');
96+
expect(classifyConnection(undefined, 0.8, { lowUpperBound: 1 })).toBe('2g');
9797
// Default would classify 0.8 as 3g, custom keeps it as 2g
9898
expect(classifyConnection(undefined, 0.8)).toBe('3g');
9999

100100
// Custom 4g upper bound
101-
expect(classifyConnection(undefined, 8, { downlink4gUpperBound: 10 })).toBe('4g');
101+
expect(classifyConnection(undefined, 8, { highUpperBound: 10 })).toBe('4g');
102102
expect(classifyConnection(undefined, 8)).toBe('high');
103103
});
104104

105105
it('effectiveType string matches are not affected by thresholds', () => {
106-
expect(classifyConnection('2g', undefined, { downlink2gUpperBound: 0.1 })).toBe('2g');
107-
expect(classifyConnection('3g', undefined, { downlink3gUpperBound: 0.1 })).toBe('3g');
106+
expect(classifyConnection('2g', undefined, { lowUpperBound: 0.1 })).toBe('2g');
107+
expect(classifyConnection('3g', undefined, { midUpperBound: 0.1 })).toBe('3g');
108108
});
109109
});
110110

@@ -204,7 +204,7 @@ describe('classify', () => {
204204
{
205205
cpu: { lowUpperBound: 4 },
206206
memory: { lowUpperBound: 4 },
207-
connection: { downlink4gUpperBound: 3 },
207+
connection: { highUpperBound: 3 },
208208
},
209209
);
210210
expect(result).toEqual({ cpu: 'low', memory: 'low', connection: 'high', gpu: 'none' });

packages/types/src/__tests__/validate.test.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ describe('validateThresholds', () => {
9999
validateThresholds({
100100
cpu: { lowUpperBound: 2, midUpperBound: 4 },
101101
memory: { lowUpperBound: 2, midUpperBound: 8 },
102-
connection: { downlink2gUpperBound: 0.5, downlink3gUpperBound: 2, downlink4gUpperBound: 5 },
102+
connection: { lowUpperBound: 0.5, midUpperBound: 2, highUpperBound: 5 },
103103
gpu: { softwarePattern: /SwiftShader/i, highEndPattern: /RTX/i },
104104
}),
105105
).not.toThrow();
@@ -138,19 +138,17 @@ describe('validateThresholds', () => {
138138
);
139139
});
140140

141-
it('throws on inverted connection bounds (2g >= 3g)', () => {
141+
it('throws on inverted connection bounds (low >= mid)', () => {
142142
expect(() =>
143-
validateThresholds({ connection: { downlink2gUpperBound: 5, downlink3gUpperBound: 2 } }),
144-
).toThrow(
145-
/connection\.downlink2gUpperBound \(5\) must be less than connection\.downlink3gUpperBound \(2\)/,
146-
);
143+
validateThresholds({ connection: { lowUpperBound: 5, midUpperBound: 2 } }),
144+
).toThrow(/connection\.lowUpperBound \(5\) must be less than connection\.midUpperBound \(2\)/);
147145
});
148146

149-
it('throws on inverted connection bounds (3g >= 4g)', () => {
147+
it('throws on inverted connection bounds (mid >= high)', () => {
150148
expect(() =>
151-
validateThresholds({ connection: { downlink3gUpperBound: 10, downlink4gUpperBound: 5 } }),
149+
validateThresholds({ connection: { midUpperBound: 10, highUpperBound: 5 } }),
152150
).toThrow(
153-
/connection\.downlink3gUpperBound \(10\) must be less than connection\.downlink4gUpperBound \(5\)/,
151+
/connection\.midUpperBound \(10\) must be less than connection\.highUpperBound \(5\)/,
154152
);
155153
});
156154

@@ -167,8 +165,8 @@ describe('validateThresholds', () => {
167165
});
168166

169167
it('throws on negative connection threshold', () => {
170-
expect(() => validateThresholds({ connection: { downlink2gUpperBound: -0.5 } })).toThrow(
171-
/connection\.downlink2gUpperBound must be positive/,
168+
expect(() => validateThresholds({ connection: { lowUpperBound: -0.5 } })).toThrow(
169+
/connection\.lowUpperBound must be positive/,
172170
);
173171
});
174172

packages/types/src/classify.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,19 @@ export function classifyConnection(
3939
downlink?: number,
4040
thresholds?: Partial<import('./thresholds.js').ConnectionThresholds>,
4141
): ConnectionTier {
42-
const { downlink2gUpperBound, downlink3gUpperBound, downlink4gUpperBound } = {
42+
const { lowUpperBound, midUpperBound, highUpperBound } = {
4343
...DEFAULT_CONNECTION_THRESHOLDS,
4444
...thresholds,
4545
};
4646

4747
if (effectiveType === 'slow-2g' || effectiveType === '2g') return '2g';
4848
if (effectiveType === '3g') return '3g';
49-
if (effectiveType === '4g' && downlink != null && downlink < downlink4gUpperBound) return '4g';
49+
if (effectiveType === '4g' && downlink != null && downlink < highUpperBound) return '4g';
5050
if (effectiveType === '4g') return 'high';
5151
if (downlink != null) {
52-
if (downlink < downlink2gUpperBound) return '2g';
53-
if (downlink < downlink3gUpperBound) return '3g';
54-
if (downlink < downlink4gUpperBound) return '4g';
52+
if (downlink < lowUpperBound) return '2g';
53+
if (downlink < midUpperBound) return '3g';
54+
if (downlink < highUpperBound) return '4g';
5555
return 'high';
5656
}
5757
return '4g';

packages/types/src/thresholds.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ export interface MemoryThresholds {
99
}
1010

1111
export interface ConnectionThresholds {
12-
downlink2gUpperBound: number;
13-
downlink3gUpperBound: number;
14-
downlink4gUpperBound: number;
12+
lowUpperBound: number;
13+
midUpperBound: number;
14+
highUpperBound: number;
1515
}
1616

1717
export interface GpuThresholds {
@@ -37,9 +37,9 @@ export const DEFAULT_MEMORY_THRESHOLDS: MemoryThresholds = {
3737
};
3838

3939
export const DEFAULT_CONNECTION_THRESHOLDS: ConnectionThresholds = {
40-
downlink2gUpperBound: 0.5,
41-
downlink3gUpperBound: 2,
42-
downlink4gUpperBound: 5,
40+
lowUpperBound: 0.5,
41+
midUpperBound: 2,
42+
highUpperBound: 5,
4343
};
4444

4545
export const DEFAULT_GPU_THRESHOLDS: GpuThresholds = {

packages/types/src/validate.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,16 @@ export function validateThresholds(thresholds: TierThresholds): void {
3131

3232
if (thresholds.connection) {
3333
const conn = { ...DEFAULT_CONNECTION_THRESHOLDS, ...thresholds.connection };
34-
if (conn.downlink2gUpperBound <= 0)
35-
errors.push('connection.downlink2gUpperBound must be positive');
36-
if (conn.downlink3gUpperBound <= 0)
37-
errors.push('connection.downlink3gUpperBound must be positive');
38-
if (conn.downlink4gUpperBound <= 0)
39-
errors.push('connection.downlink4gUpperBound must be positive');
40-
if (conn.downlink2gUpperBound >= conn.downlink3gUpperBound)
34+
if (conn.lowUpperBound <= 0) errors.push('connection.lowUpperBound must be positive');
35+
if (conn.midUpperBound <= 0) errors.push('connection.midUpperBound must be positive');
36+
if (conn.highUpperBound <= 0) errors.push('connection.highUpperBound must be positive');
37+
if (conn.lowUpperBound >= conn.midUpperBound)
4138
errors.push(
42-
`connection.downlink2gUpperBound (${conn.downlink2gUpperBound}) must be less than connection.downlink3gUpperBound (${conn.downlink3gUpperBound})`,
39+
`connection.lowUpperBound (${conn.lowUpperBound}) must be less than connection.midUpperBound (${conn.midUpperBound})`,
4340
);
44-
if (conn.downlink3gUpperBound >= conn.downlink4gUpperBound)
41+
if (conn.midUpperBound >= conn.highUpperBound)
4542
errors.push(
46-
`connection.downlink3gUpperBound (${conn.downlink3gUpperBound}) must be less than connection.downlink4gUpperBound (${conn.downlink4gUpperBound})`,
43+
`connection.midUpperBound (${conn.midUpperBound}) must be less than connection.highUpperBound (${conn.highUpperBound})`,
4744
);
4845
}
4946

0 commit comments

Comments
 (0)