• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LukaJCB / ts-mls / 20945201760

13 Jan 2026 04:55AM UTC coverage: 95.199% (-0.5%) from 95.727%
20945201760

push

github

web-flow
Use CiphersuiteId instead of CiphersuiteName for internal values (#200)

* Use CiphersuiteId instead of CiphersuiteName for internal values

* Use ProtocolVersionValue instead of ProtocolVersionName

* Use CredentialTypeValue instead of CredentialTypeName

* Use DefaultProposalTypeValue instead of DefaultProposalTypeName

* Remove extensionType

* Refactor credential

* Cleanup

* Use LeafNodeSourceValue insteda of Name

* Cleanup

* Update NodeType and LeafNodeSource

* Update contentType

* Update resumptionPskusage & senderTypes

* Update wireformat and pskTypes

* Update ts-mls.api

412 of 421 branches covered (97.86%)

Branch coverage included in aggregate %.

193 of 208 new or added lines in 35 files covered. (92.79%)

6 existing lines in 3 files now uncovered.

2364 of 2495 relevant lines covered (94.75%)

75088.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.65
/src/proposal.ts
1
import { decodeUint16, decodeUint32, uint16Encoder, uint32Encoder } from "./codec/number.js"
2
import { Decoder, flatMapDecoder, mapDecoder, mapDecoders, orDecoder } from "./codec/tlsDecoder.js"
3
import { contramapBufferEncoder, contramapBufferEncoders, BufferEncoder, encode, Encoder } from "./codec/tlsEncoder.js"
4
import { decodeVarLenData, decodeVarLenType, varLenDataEncoder, varLenTypeEncoder } from "./codec/variableLength.js"
5
import { CiphersuiteId, ciphersuiteEncoder, decodeCiphersuite } from "./crypto/ciphersuite.js"
6
import { decodeExtension, extensionEncoder, Extension } from "./extension.js"
7
import { decodeKeyPackage, keyPackageEncoder, KeyPackage } from "./keyPackage.js"
8
import { decodePskId, pskIdEncoder, PreSharedKeyID } from "./presharedkey.js"
9
import {
10
  decodeDefaultProposalTypeValue,
11
  defaultProposalTypeValueEncoder,
12
  defaultProposalTypes,
13
  isDefaultProposalTypeValue,
14
} from "./defaultProposalType.js"
15
import { decodeProtocolVersion, protocolVersionEncoder, ProtocolVersionValue } from "./protocolVersion.js"
16
import { decodeLeafNodeUpdate, leafNodeEncoder, LeafNodeUpdate } from "./leafNode.js"
17

18
/** @public */
19
export interface Add {
20
  keyPackage: KeyPackage
21
}
22

23
export const addEncoder: BufferEncoder<Add> = contramapBufferEncoder(keyPackageEncoder, (a) => a.keyPackage)
2,817✔
24

25
export const encodeAdd: Encoder<Add> = encode(addEncoder)
3✔
26
export const decodeAdd: Decoder<Add> = mapDecoder(decodeKeyPackage, (keyPackage) => ({ keyPackage }))
1,005✔
27

28
/** @public */
29
export interface Update {
30
  leafNode: LeafNodeUpdate
31
}
32

33
export const updateEncoder: BufferEncoder<Update> = contramapBufferEncoder(leafNodeEncoder, (u) => u.leafNode)
342✔
34

35
export const encodeUpdate: Encoder<Update> = encode(updateEncoder)
3✔
36
export const decodeUpdate: Decoder<Update> = mapDecoder(decodeLeafNodeUpdate, (leafNode) => ({ leafNode }))
315✔
37

38
/** @public */
39
export interface Remove {
40
  removed: number
41
}
42

43
export const removeEncoder: BufferEncoder<Remove> = contramapBufferEncoder(uint32Encoder, (r) => r.removed)
7,034✔
44

45
export const encodeRemove: Encoder<Remove> = encode(removeEncoder)
3✔
46
export const decodeRemove: Decoder<Remove> = mapDecoder(decodeUint32, (removed) => ({ removed }))
2,460✔
47

48
/** @public */
49
export interface PSK {
50
  preSharedKeyId: PreSharedKeyID
51
}
52

53
export const pskEncoder: BufferEncoder<PSK> = contramapBufferEncoder(pskIdEncoder, (p) => p.preSharedKeyId)
512✔
54

55
export const encodePSK: Encoder<PSK> = encode(pskEncoder)
3✔
56
export const decodePSK: Decoder<PSK> = mapDecoder(decodePskId, (preSharedKeyId) => ({ preSharedKeyId }))
429✔
57

58
/** @public */
59
export interface Reinit {
60
  groupId: Uint8Array
61
  version: ProtocolVersionValue
62
  cipherSuite: CiphersuiteId
63
  extensions: Extension[]
64
}
65

66
export const reinitEncoder: BufferEncoder<Reinit> = contramapBufferEncoders(
3✔
67
  [varLenDataEncoder, protocolVersionEncoder, ciphersuiteEncoder, varLenTypeEncoder(extensionEncoder)],
68
  (r) => [r.groupId, r.version, r.cipherSuite, r.extensions] as const,
494✔
69
)
70

71
export const encodeReinit: Encoder<Reinit> = encode(reinitEncoder)
3✔
72

73
export const decodeReinit: Decoder<Reinit> = mapDecoders(
3✔
74
  [decodeVarLenData, decodeProtocolVersion, decodeCiphersuite, decodeVarLenType(decodeExtension)],
75
  (groupId, version, cipherSuite, extensions) => ({ groupId, version, cipherSuite, extensions }),
339✔
76
)
77

78
/** @public */
79
export interface ExternalInit {
80
  kemOutput: Uint8Array
81
}
82

83
export const externalInitEncoder: BufferEncoder<ExternalInit> = contramapBufferEncoder(
3✔
84
  varLenDataEncoder,
85
  (e) => e.kemOutput,
528✔
86
)
87

88
export const encodeExternalInit: Encoder<ExternalInit> = encode(externalInitEncoder)
3✔
89
export const decodeExternalInit: Decoder<ExternalInit> = mapDecoder(decodeVarLenData, (kemOutput) => ({ kemOutput }))
300✔
90

91
/** @public */
92
export interface GroupContextExtensions {
93
  extensions: Extension[]
94
}
95

96
export const groupContextExtensionsEncoder: BufferEncoder<GroupContextExtensions> = contramapBufferEncoder(
3✔
97
  varLenTypeEncoder(extensionEncoder),
98
  (g) => g.extensions,
555✔
99
)
100

101
export const encodeGroupContextExtensions: Encoder<GroupContextExtensions> = encode(groupContextExtensionsEncoder)
3✔
102

103
export const decodeGroupContextExtensions: Decoder<GroupContextExtensions> = mapDecoder(
3✔
104
  decodeVarLenType(decodeExtension),
105
  (extensions) => ({ extensions }),
347✔
106
)
107

108
/** @public */
109
export interface ProposalAdd {
110
  proposalType: typeof defaultProposalTypes.add
111
  add: Add
112
}
113

114
/** @public */
115
export interface ProposalUpdate {
116
  proposalType: typeof defaultProposalTypes.update
117
  update: Update
118
}
119

120
/** @public */
121
export interface ProposalRemove {
122
  proposalType: typeof defaultProposalTypes.remove
123
  remove: Remove
124
}
125

126
/** @public */
127
export interface ProposalPSK {
128
  proposalType: typeof defaultProposalTypes.psk
129
  psk: PSK
130
}
131

132
/** @public */
133
export interface ProposalReinit {
134
  proposalType: typeof defaultProposalTypes.reinit
135
  reinit: Reinit
136
}
137

138
/** @public */
139
export interface ProposalExternalInit {
140
  proposalType: typeof defaultProposalTypes.external_init
141
  externalInit: ExternalInit
142
}
143

144
/** @public */
145
export interface ProposalGroupContextExtensions {
146
  proposalType: typeof defaultProposalTypes.group_context_extensions
147
  groupContextExtensions: GroupContextExtensions
148
}
149

150
/** @public */
151
export interface ProposalCustom {
152
  proposalType: number
153
  proposalData: Uint8Array
154
}
155

156
/** @public */
157
export type DefaultProposal =
158
  | ProposalAdd
159
  | ProposalUpdate
160
  | ProposalRemove
161
  | ProposalPSK
162
  | ProposalReinit
163
  | ProposalExternalInit
164
  | ProposalGroupContextExtensions
165

166
/** @public */
167
export type Proposal = DefaultProposal | ProposalCustom
168

169
export function isDefaultProposal(p: Proposal): p is DefaultProposal {
170
  return isDefaultProposalTypeValue(p.proposalType)
19,524✔
171
}
172

173
export const proposalAddEncoder: BufferEncoder<ProposalAdd> = contramapBufferEncoders(
3✔
174
  [defaultProposalTypeValueEncoder, addEncoder],
175
  (p) => [p.proposalType, p.add] as const,
2,514✔
176
)
177

178
export const encodeProposalAdd: Encoder<ProposalAdd> = encode(proposalAddEncoder)
3✔
179

180
export const proposalUpdateEncoder: BufferEncoder<ProposalUpdate> = contramapBufferEncoders(
3✔
181
  [defaultProposalTypeValueEncoder, updateEncoder],
182
  (p) => [p.proposalType, p.update] as const,
42✔
183
)
184

185
export const encodeProposalUpdate: Encoder<ProposalUpdate> = encode(proposalUpdateEncoder)
3✔
186

187
export const proposalRemoveEncoder: BufferEncoder<ProposalRemove> = contramapBufferEncoders(
3✔
188
  [defaultProposalTypeValueEncoder, removeEncoder],
189
  (p) => [p.proposalType, p.remove] as const,
6,734✔
190
)
191

192
export const encodeProposalRemove: Encoder<ProposalRemove> = encode(proposalRemoveEncoder)
3✔
193

194
export const proposalPSKEncoder: BufferEncoder<ProposalPSK> = contramapBufferEncoders(
3✔
195
  [defaultProposalTypeValueEncoder, pskEncoder],
196
  (p) => [p.proposalType, p.psk] as const,
627✔
197
)
198

199
export const encodeProposalPSK: Encoder<ProposalPSK> = encode(proposalPSKEncoder)
3✔
200

201
export const proposalReinitEncoder: BufferEncoder<ProposalReinit> = contramapBufferEncoders(
3✔
202
  [defaultProposalTypeValueEncoder, reinitEncoder],
203
  (p) => [p.proposalType, p.reinit] as const,
193✔
204
)
205

206
export const encodeProposalReinit: Encoder<ProposalReinit> = encode(proposalReinitEncoder)
3✔
207

208
export const proposalExternalInitEncoder: BufferEncoder<ProposalExternalInit> = contramapBufferEncoders(
3✔
209
  [defaultProposalTypeValueEncoder, externalInitEncoder],
210
  (p) => [p.proposalType, p.externalInit] as const,
228✔
211
)
212

213
export const encodeProposalExternalInit: Encoder<ProposalExternalInit> = encode(proposalExternalInitEncoder)
3✔
214

215
export const proposalGroupContextExtensionsEncoder: BufferEncoder<ProposalGroupContextExtensions> =
3✔
216
  contramapBufferEncoders(
217
    [defaultProposalTypeValueEncoder, groupContextExtensionsEncoder],
218
    (p) => [p.proposalType, p.groupContextExtensions] as const,
255✔
219
  )
220

221
export const encodeProposalGroupContextExtensions: Encoder<ProposalGroupContextExtensions> = encode(
3✔
222
  proposalGroupContextExtensionsEncoder,
223
)
224

225
export const proposalCustomEncoder: BufferEncoder<ProposalCustom> = contramapBufferEncoders(
3✔
226
  [uint16Encoder, varLenDataEncoder],
227
  (p) => [p.proposalType, p.proposalData] as const,
171✔
228
)
229

230
export const encodeProposalCustom: Encoder<ProposalCustom> = encode(proposalCustomEncoder)
3✔
231

232
export const proposalEncoder: BufferEncoder<Proposal> = (p) => {
3✔
233
  if (!isDefaultProposal(p)) return proposalCustomEncoder(p)
17,539✔
234

235
  switch (p.proposalType) {
17,368✔
236
    case defaultProposalTypes.add:
237
      return proposalAddEncoder(p)
9,094✔
238
    case defaultProposalTypes.update:
239
      return proposalUpdateEncoder(p)
42✔
240
    case defaultProposalTypes.remove:
241
      return proposalRemoveEncoder(p)
6,872✔
242
    case defaultProposalTypes.psk:
243
      return proposalPSKEncoder(p)
684✔
244
    case defaultProposalTypes.reinit:
245
      return proposalReinitEncoder(p)
193✔
246
    case defaultProposalTypes.external_init:
247
      return proposalExternalInitEncoder(p)
228✔
248
    case defaultProposalTypes.group_context_extensions:
249
      return proposalGroupContextExtensionsEncoder(p)
255✔
250
  }
251
}
252

253
export const encodeProposal: Encoder<Proposal> = encode(proposalEncoder)
3✔
254

255
export const decodeProposalAdd: Decoder<ProposalAdd> = mapDecoder(decodeAdd, (add) => ({
2,274✔
256
  proposalType: defaultProposalTypes.add,
257
  add,
258
}))
259

260
export const decodeProposalUpdate: Decoder<ProposalUpdate> = mapDecoder(decodeUpdate, (update) => ({
15✔
261
  proposalType: defaultProposalTypes.update,
262
  update,
263
}))
264

265
export const decodeProposalRemove: Decoder<ProposalRemove> = mapDecoder(decodeRemove, (remove) => ({
2,160✔
266
  proposalType: defaultProposalTypes.remove,
267
  remove,
268
}))
269

270
export const decodeProposalPSK: Decoder<ProposalPSK> = mapDecoder(decodePSK, (psk) => ({
129✔
271
  proposalType: defaultProposalTypes.psk,
272
  psk,
273
}))
274

275
export const decodeProposalReinit: Decoder<ProposalReinit> = mapDecoder(decodeReinit, (reinit) => ({
38✔
276
  proposalType: defaultProposalTypes.reinit,
277
  reinit,
278
}))
279

280
export const decodeProposalExternalInit: Decoder<ProposalExternalInit> = mapDecoder(
3✔
281
  decodeExternalInit,
NEW
282
  (externalInit) => ({ proposalType: defaultProposalTypes.external_init, externalInit }),
×
283
)
284

285
export const decodeProposalGroupContextExtensions: Decoder<ProposalGroupContextExtensions> = mapDecoder(
3✔
286
  decodeGroupContextExtensions,
287
  (groupContextExtensions) => ({
47✔
288
    proposalType: defaultProposalTypes.group_context_extensions,
289
    groupContextExtensions,
290
  }),
291
)
292

293
export function decodeProposalCustom(proposalType: number): Decoder<ProposalCustom> {
294
  return mapDecoder(decodeVarLenData, (proposalData) => ({ proposalType, proposalData }))
38✔
295
}
296

297
export const decodeProposal: Decoder<Proposal> = orDecoder(
3✔
298
  flatMapDecoder(decodeDefaultProposalTypeValue, (proposalType): Decoder<Proposal> => {
299
    switch (proposalType) {
4,726✔
300
      case defaultProposalTypes.add:
301
        return decodeProposalAdd
2,296✔
302
      case defaultProposalTypes.update:
303
        return decodeProposalUpdate
15✔
304
      case defaultProposalTypes.remove:
305
        return decodeProposalRemove
2,201✔
306
      case defaultProposalTypes.psk:
307
        return decodeProposalPSK
129✔
308
      case defaultProposalTypes.reinit:
309
        return decodeProposalReinit
38✔
310
      case defaultProposalTypes.external_init:
311
        return decodeProposalExternalInit
×
312
      case defaultProposalTypes.group_context_extensions:
313
        return decodeProposalGroupContextExtensions
47✔
314
    }
315
  }),
316
  flatMapDecoder(decodeUint16, (n) => decodeProposalCustom(n)),
38✔
317
)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc