@vinikjkkj/wa-abprops 2.3000.1044071294-e8a5558
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/README.md +223 -0
- package/index.d.ts +4402 -0
- package/index.js +4372 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# @vinikjkkj/wa-abprops
|
|
2
|
+
|
|
3
|
+
WhatsApp Web AB props (server-driven experiment configs) — the numeric config
|
|
4
|
+
code each prop travels under, its wire value type, its client-side default and
|
|
5
|
+
its internal-build debug default. Everything is daily-extracted directly from
|
|
6
|
+
the minified `WAWebABPropsConfigs` / `WAWebGroupABPropsConfigs` tables in WA
|
|
7
|
+
Web bundles.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm i @vinikjkkj/wa-abprops
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import {
|
|
15
|
+
WA_ABPROPS,
|
|
16
|
+
WA_GROUP_ABPROPS,
|
|
17
|
+
WA_ABPROPS_BY_CODE, // reverse map: 6939 → 'adv_accept_hosted_devices'
|
|
18
|
+
WA_GROUP_ABPROPS_BY_CODE,
|
|
19
|
+
WA_ABPROPS_USED_BEFORE_INIT, // readable before the config cache resolves
|
|
20
|
+
WA_ABPROPS_SPECIAL_EARLY // mirrored into localStorage for pre-DB startup code
|
|
21
|
+
} from '@vinikjkkj/wa-abprops'
|
|
22
|
+
import type {
|
|
23
|
+
WaAbPropName,
|
|
24
|
+
WaGroupAbPropName,
|
|
25
|
+
WaAbProp,
|
|
26
|
+
WaAbPropType,
|
|
27
|
+
WaAbPropValueByName
|
|
28
|
+
} from '@vinikjkkj/wa-abprops'
|
|
29
|
+
|
|
30
|
+
WA_ABPROPS.web_image_max_edge
|
|
31
|
+
// → { code: 3042, type: 'int', defaultValue: 1600, debugDefaultValue: 1600 }
|
|
32
|
+
|
|
33
|
+
WA_ABPROPS.adv_accept_hosted_devices
|
|
34
|
+
// → { code: 6939, type: 'bool', defaultValue: false, debugDefaultValue: true }
|
|
35
|
+
// defaultValue ≠ debugDefaultValue → shipped off, on for internal builds
|
|
36
|
+
|
|
37
|
+
WA_ABPROPS.a2ui_supported_elements
|
|
38
|
+
// → {
|
|
39
|
+
// code: 32276,
|
|
40
|
+
// type: 'string',
|
|
41
|
+
// defaultValue: 'info_card, list_card',
|
|
42
|
+
// debugDefaultValue: 'info_card, list_card'
|
|
43
|
+
// }
|
|
44
|
+
|
|
45
|
+
WA_GROUP_ABPROPS.group_history_messages_time_limit_secs_group_level
|
|
46
|
+
// → { code: 26270, type: 'int', defaultValue: 1209600, debugDefaultValue: 1209600 }
|
|
47
|
+
|
|
48
|
+
WA_ABPROPS_SPECIAL_EARLY
|
|
49
|
+
// → {
|
|
50
|
+
// localStorageKey: 'abprops_needed_early',
|
|
51
|
+
// props: ['wa_web_favicons_update_m1', 'web_ui_refresh_m1', …]
|
|
52
|
+
// }
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Decoding a server response
|
|
56
|
+
|
|
57
|
+
The `abt` IQ hands back rows of `{ configCode, configValue, configExpoKey }`
|
|
58
|
+
where `configValue` is *always* a string. This package gives you both halves
|
|
59
|
+
of the decode: the code → name mapping and the type to parse with.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { WA_ABPROPS, WA_ABPROPS_BY_CODE } from '@vinikjkkj/wa-abprops'
|
|
63
|
+
|
|
64
|
+
function parseConfigValue(raw: string, type: WaAbPropType, fallback: unknown) {
|
|
65
|
+
if (raw == null) return fallback
|
|
66
|
+
if (type === 'bool') return raw === '1' || raw === 'true' || raw === 'True'
|
|
67
|
+
if (type === 'int') return parseInt(raw, 10)
|
|
68
|
+
if (type === 'float') return parseFloat(raw)
|
|
69
|
+
return raw
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function decode(rows: Array<{ configCode: string; configValue: string }>) {
|
|
73
|
+
const out: Record<string, unknown> = {}
|
|
74
|
+
for (const row of rows) {
|
|
75
|
+
const name = WA_ABPROPS_BY_CODE[Number(row.configCode) as keyof typeof WA_ABPROPS_BY_CODE]
|
|
76
|
+
if (name == null) continue // prop the client build doesn't know yet
|
|
77
|
+
const prop = WA_ABPROPS[name]
|
|
78
|
+
out[name] = parseConfigValue(row.configValue, prop.type, prop.defaultValue)
|
|
79
|
+
}
|
|
80
|
+
return out
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Props the server never sent keep their `defaultValue` — that is exactly what
|
|
85
|
+
`WAWebABProps.getABPropConfigValue` does when the cache misses.
|
|
86
|
+
|
|
87
|
+
## Typed lookups
|
|
88
|
+
|
|
89
|
+
Every prop is emitted with literal types, so `WaAbPropValueByName<K>` resolves
|
|
90
|
+
a prop's decoded JS type from its declared wire type:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import type { WaAbPropValueByName } from '@vinikjkkj/wa-abprops'
|
|
94
|
+
|
|
95
|
+
type MaxEdge = WaAbPropValueByName<'web_image_max_edge'> // → number
|
|
96
|
+
type Hosted = WaAbPropValueByName<'adv_accept_hosted_devices'> // → boolean
|
|
97
|
+
type Elements = WaAbPropValueByName<'a2ui_supported_elements'> // → string
|
|
98
|
+
|
|
99
|
+
function getAbProp<K extends WaAbPropName>(name: K): WaAbPropValueByName<K> {
|
|
100
|
+
// …your cache lookup, falling back to WA_ABPROPS[name].defaultValue
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getAbProp('web_image_max_edge') // ✓ number
|
|
104
|
+
getAbProp('web_image_max_edg') // ✗ caught at compile time
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The `code` and both default values are literal types too, so
|
|
108
|
+
`WA_ABPROPS.adv_accept_hosted_devices.code` narrows to `6939` rather than
|
|
109
|
+
`number`.
|
|
110
|
+
|
|
111
|
+
## What's in here
|
|
112
|
+
|
|
113
|
+
Nearly every feature in WA Web sits behind an AB prop. The client ships the
|
|
114
|
+
full catalogue as a flat data table and asks the server, at connect, for the
|
|
115
|
+
values it should use:
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
// from WAWebABPropsConfigs — <name>: [configCode, type, default, debugDefault]
|
|
119
|
+
var e = {
|
|
120
|
+
adv_accept_hosted_devices: [6939, 'bool', false, true],
|
|
121
|
+
web_image_max_edge: [3042, 'int', 1600, 1600],
|
|
122
|
+
a2ui_supported_elements: [32276, 'string', 'info_card, list_card', 'info_card, list_card'],
|
|
123
|
+
// …2000+ more
|
|
124
|
+
}
|
|
125
|
+
i.ABPropConfigs = e
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Each entry boils down to:
|
|
129
|
+
|
|
130
|
+
- a **config code** (`6939`) — the *only* identity that travels on the wire.
|
|
131
|
+
The IQ (`WASmaxAbPropsGetExperimentConfigRPC`) returns rows keyed by code,
|
|
132
|
+
and the local `abpropConfigs` table uses it as its primary key. Prop names
|
|
133
|
+
never leave the client, which is why the reverse map matters.
|
|
134
|
+
- a **name** (`adv_accept_hosted_devices`) — the handle every
|
|
135
|
+
`getABPropConfigValue('…')` call site uses
|
|
136
|
+
- a **type** — `bool` | `int` | `float` | `string`. The server's
|
|
137
|
+
`configValue` is always a string; this drives
|
|
138
|
+
`WAWebABPropsParseConfigValue.parseConfigValue`.
|
|
139
|
+
- a **default value** — used whenever the server hasn't pushed a value for
|
|
140
|
+
this code (cache miss, offline, brand-new prop)
|
|
141
|
+
- a **debug default value** — substituted for the default only on internal
|
|
142
|
+
builds (gkx 26259 on *and* the account joined the internal beta;
|
|
143
|
+
`WAWebABPropsUpdateFromStorage` logs *"intern beta joined, using DEBUG
|
|
144
|
+
defaults"*). It's identical to the default for most props — where the two
|
|
145
|
+
differ, the debug value is a decent signal of where the rollout is headed.
|
|
146
|
+
|
|
147
|
+
Group-scoped props live in a parallel table (`WAWebGroupABPropsConfigs`),
|
|
148
|
+
fetched per group jid via the group experiment config IQ and cached separately.
|
|
149
|
+
|
|
150
|
+
Two auxiliary lists ship alongside:
|
|
151
|
+
|
|
152
|
+
- **`WA_ABPROPS_USED_BEFORE_INIT`** — the allowlist of props the runtime
|
|
153
|
+
tolerates reading before the config cache resolves. Everything else logs
|
|
154
|
+
*"impl must be set before first access"* and silently yields the default.
|
|
155
|
+
- **`WA_ABPROPS_SPECIAL_EARLY`** — the handful of props mirrored into
|
|
156
|
+
`localStorage` (as a JSON object under `abprops_needed_early`) so startup
|
|
157
|
+
code can consult them before IndexedDB opens.
|
|
158
|
+
|
|
159
|
+
This package gives you the static metadata for all **2100+ user props** +
|
|
160
|
+
**14 group props**, so you can decode an `abt` response, mirror WA Web's
|
|
161
|
+
gating decisions, or diff a build's rollout state without transcribing the
|
|
162
|
+
client's table by hand.
|
|
163
|
+
|
|
164
|
+
## What's published
|
|
165
|
+
|
|
166
|
+
| File | Format | Use case |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `index.js` | CommonJS | Runtime `WA_ABPROPS` / `WA_GROUP_ABPROPS` / `WA_ABPROPS_BY_CODE` / `WA_GROUP_ABPROPS_BY_CODE` / `WA_ABPROPS_USED_BEFORE_INIT` / `WA_ABPROPS_SPECIAL_EARLY` frozen tables |
|
|
169
|
+
| `index.d.ts` | TS declarations | Per-prop literal-typed entries + the umbrella maps + the `WaAbPropValueByName<K>` helper |
|
|
170
|
+
|
|
171
|
+
A raw IR file (`index.json`) is also produced — see
|
|
172
|
+
[`packages/abprops/index.json`](https://github.com/vinikjkkj/wa-spec/blob/master/packages/abprops/index.json)
|
|
173
|
+
for non-TS consumers (diff tools, codegen, other languages).
|
|
174
|
+
|
|
175
|
+
`index.json` shape:
|
|
176
|
+
|
|
177
|
+
```jsonc
|
|
178
|
+
{
|
|
179
|
+
"waVersion": "2.3000.xxxxx",
|
|
180
|
+
"propCount": 2117,
|
|
181
|
+
"groupPropCount": 14,
|
|
182
|
+
"usedBeforeInitialization": ["direct_connection_business_numbers", …],
|
|
183
|
+
"specialEarlyProps": {
|
|
184
|
+
"localStorageKey": "abprops_needed_early",
|
|
185
|
+
"props": ["wa_web_favicons_update_m1", "web_ui_refresh_m1", …]
|
|
186
|
+
},
|
|
187
|
+
"props": {
|
|
188
|
+
"adv_accept_hosted_devices": {
|
|
189
|
+
"code": 6939,
|
|
190
|
+
"type": "bool",
|
|
191
|
+
"defaultValue": false,
|
|
192
|
+
"debugDefaultValue": true
|
|
193
|
+
},
|
|
194
|
+
…
|
|
195
|
+
},
|
|
196
|
+
"groupProps": {
|
|
197
|
+
"group_history_messages_time_limit_secs_group_level": {
|
|
198
|
+
"code": 26270,
|
|
199
|
+
"type": "int",
|
|
200
|
+
"defaultValue": 1209600,
|
|
201
|
+
"debugDefaultValue": 1209600
|
|
202
|
+
},
|
|
203
|
+
…
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Gotchas
|
|
209
|
+
|
|
210
|
+
- **Names are client-only.** A code with no entry in `WA_ABPROPS_BY_CODE` is
|
|
211
|
+
a prop the server knows about but this build doesn't — skip it rather than
|
|
212
|
+
guessing. The runtime does the same (it warns and drops the row).
|
|
213
|
+
- **Defaults are not "off".** Plenty of props default to a non-trivial int or
|
|
214
|
+
string; treating a missing value as `false` will diverge from the client.
|
|
215
|
+
- **`debugDefaultValue` is not what you'll be served.** It only applies to
|
|
216
|
+
internal builds. Use `defaultValue` when modelling a normal client.
|
|
217
|
+
- **Codes are stable, values are not.** A prop's `code` persists across
|
|
218
|
+
builds; its defaults change freely, and props are added and removed every
|
|
219
|
+
release. Diff `index.json` between versions to see the movement.
|
|
220
|
+
- **Group props are a separate namespace.** `WA_GROUP_ABPROPS` codes come
|
|
221
|
+
from their own table and are not interchangeable with user-level codes.
|
|
222
|
+
|
|
223
|
+
Daily-extracted by [wa-spec](https://github.com/vinikjkkj/wa-spec).
|