@nmtjs/protocol 0.8.1 → 0.10.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 (64) hide show
  1. package/dist/client/events.js +2 -0
  2. package/dist/client/events.js.map +1 -1
  3. package/dist/client/format.js +2 -0
  4. package/dist/client/format.js.map +1 -1
  5. package/dist/client/index.js +3 -0
  6. package/dist/client/index.js.map +1 -1
  7. package/dist/client/protocol.js +205 -199
  8. package/dist/client/protocol.js.map +1 -1
  9. package/dist/client/stream.js +9 -12
  10. package/dist/client/stream.js.map +1 -1
  11. package/dist/client/types.js +3 -0
  12. package/dist/client/types.js.map +1 -0
  13. package/dist/common/binary.js +2 -0
  14. package/dist/common/binary.js.map +1 -1
  15. package/dist/common/blob.js +6 -2
  16. package/dist/common/blob.js.map +1 -1
  17. package/dist/common/enums.js +4 -1
  18. package/dist/common/enums.js.map +1 -1
  19. package/dist/common/index.js +2 -0
  20. package/dist/common/index.js.map +1 -1
  21. package/dist/common/types.js +2 -0
  22. package/dist/common/types.js.map +1 -1
  23. package/dist/server/api.js +4 -1
  24. package/dist/server/api.js.map +1 -1
  25. package/dist/server/connection.js +2 -0
  26. package/dist/server/connection.js.map +1 -1
  27. package/dist/server/constants.js +2 -0
  28. package/dist/server/constants.js.map +1 -1
  29. package/dist/server/format.js +2 -0
  30. package/dist/server/format.js.map +1 -1
  31. package/dist/server/index.js +3 -0
  32. package/dist/server/index.js.map +1 -1
  33. package/dist/server/injectables.js +2 -0
  34. package/dist/server/injectables.js.map +1 -1
  35. package/dist/server/protocol.js +154 -55
  36. package/dist/server/protocol.js.map +1 -1
  37. package/dist/server/registry.js +2 -0
  38. package/dist/server/registry.js.map +1 -1
  39. package/dist/server/stream.js +3 -1
  40. package/dist/server/stream.js.map +1 -1
  41. package/dist/server/transport.js +2 -0
  42. package/dist/server/transport.js.map +1 -1
  43. package/dist/server/types.js +3 -0
  44. package/dist/server/types.js.map +1 -0
  45. package/dist/server/utils.js +7 -2
  46. package/dist/server/utils.js.map +1 -1
  47. package/package.json +8 -8
  48. package/src/client/format.ts +34 -5
  49. package/src/client/index.ts +2 -0
  50. package/src/client/protocol.ts +381 -274
  51. package/src/client/stream.ts +7 -14
  52. package/src/client/types.ts +14 -0
  53. package/src/common/blob.ts +10 -3
  54. package/src/common/enums.ts +3 -1
  55. package/src/common/types.ts +28 -47
  56. package/src/server/api.ts +15 -1
  57. package/src/server/connection.ts +1 -5
  58. package/src/server/format.ts +14 -4
  59. package/src/server/index.ts +1 -0
  60. package/src/server/protocol.ts +208 -66
  61. package/src/server/stream.ts +2 -7
  62. package/src/server/transport.ts +5 -1
  63. package/src/server/types.ts +21 -0
  64. package/src/server/utils.ts +9 -2
@@ -1,16 +1,27 @@
1
- import { type Callback, createPromise, defer, throwError } from '@nmtjs/common'
2
- import { type Container, Hook, type Logger, Scope } from '@nmtjs/core'
1
+ import { type Callback, defer, throwError } from '@nmtjs/common'
2
+ import {
3
+ type AnyInjectable,
4
+ type Container,
5
+ Hook,
6
+ type Logger,
7
+ Scope,
8
+ } from '@nmtjs/core'
3
9
  import { concat, decodeNumber, encodeNumber } from '../common/binary.ts'
4
10
  import type { ProtocolBlob, ProtocolBlobMetadata } from '../common/blob.ts'
5
11
  import { ErrorCode, ServerMessageType } from '../common/enums.ts'
6
12
  import type { ProtocolRPC } from '../common/types.ts'
7
- import type { ProtocolApi, ProtocolApiCallResult } from './api.ts'
13
+ import {
14
+ isIterableResult,
15
+ type ProtocolApi,
16
+ type ProtocolApiCallOptions,
17
+ } from './api.ts'
8
18
  import {
9
19
  Connection,
10
20
  ConnectionContext,
11
21
  type ConnectionOptions,
12
22
  } from './connection.ts'
13
23
  import type { Format } from './format.ts'
24
+ import { ProtocolInjectables } from './injectables.ts'
14
25
  import type { ProtocolRegistry } from './registry.ts'
15
26
  import { ProtocolClientStream, ProtocolServerStream } from './stream.ts'
16
27
  import type { Transport } from './transport.ts'
@@ -43,13 +54,17 @@ export class ProtocolError extends Error {
43
54
  }
44
55
  }
45
56
 
57
+ export type ProtocolConnectionTransport = {
58
+ send: Transport<any>['send']
59
+ }
60
+
46
61
  export class ProtocolConnections {
47
62
  readonly #collection = new Map<
48
63
  string,
49
64
  {
50
65
  connection: Connection
51
66
  context: ConnectionContext
52
- transport: Transport
67
+ transport: ProtocolConnectionTransport
53
68
  }
54
69
  >()
55
70
 
@@ -69,7 +84,7 @@ export class ProtocolConnections {
69
84
  }
70
85
 
71
86
  async add<T>(
72
- transport: Transport<any>,
87
+ transport: ProtocolConnectionTransport,
73
88
  options: ConnectionOptions<T>,
74
89
  params: ResolveFormatParams,
75
90
  ) {
@@ -77,16 +92,19 @@ export class ProtocolConnections {
77
92
  const format = getFormat(this.application.format, params)
78
93
  const container = this.application.container.fork(Scope.Connection)
79
94
  const context = new ConnectionContext(container, format)
80
-
81
- this.#collection.set(connection.id, { connection, context, transport })
82
-
83
- await this.application.registry.hooks.call(
84
- Hook.OnConnect,
85
- { concurrent: false },
86
- connection,
87
- )
88
-
89
- return { connection, context }
95
+ container.provide(ProtocolInjectables.connection, connection)
96
+ try {
97
+ await this.initialize(connection)
98
+ this.#collection.set(connection.id, { connection, context, transport })
99
+ return { connection, context }
100
+ } finally {
101
+ container.dispose().catch((error) => {
102
+ this.application.logger.error(
103
+ { error, connection },
104
+ 'Error during disposing connection',
105
+ )
106
+ })
107
+ }
90
108
  }
91
109
 
92
110
  async remove(connectionId: string) {
@@ -128,6 +146,14 @@ export class ProtocolConnections {
128
146
  )
129
147
  }
130
148
  }
149
+
150
+ async initialize(connection: Connection) {
151
+ await this.application.registry.hooks.call(
152
+ Hook.OnConnect,
153
+ { concurrent: false },
154
+ connection,
155
+ )
156
+ }
131
157
  }
132
158
 
133
159
  export class ProtocolClientStreams {
@@ -162,12 +188,12 @@ export class ProtocolClientStreams {
162
188
 
163
189
  push(connectionId: string, streamId: number, chunk: ArrayBuffer) {
164
190
  const stream = this.get(connectionId, streamId)
165
- stream.push(Buffer.from(chunk))
191
+ stream.write(Buffer.from(chunk))
166
192
  }
167
193
 
168
194
  end(connectionId: string, streamId: number) {
169
195
  const stream = this.get(connectionId, streamId)
170
- stream.push(null)
196
+ stream.end(null)
171
197
  this.remove(connectionId, streamId)
172
198
  }
173
199
 
@@ -204,6 +230,7 @@ export class ProtocolServerStreams {
204
230
  }
205
231
 
206
232
  pull(connectionId: string, streamId: number) {
233
+ console.log('Pulling stream', streamId)
207
234
  const stream = this.get(connectionId, streamId)
208
235
  stream.resume()
209
236
  }
@@ -215,10 +242,16 @@ export class ProtocolServerStreams {
215
242
  }
216
243
  }
217
244
 
245
+ export type ProtocolRPCOptions = {
246
+ signal?: AbortSignal
247
+ provides?: [AnyInjectable, any][]
248
+ metadata?: ProtocolApiCallOptions['metadata']
249
+ }
250
+
218
251
  export class Protocol {
219
- readonly connections: ProtocolConnections
220
- readonly clientStreams: ProtocolClientStreams
221
- readonly serverStreams: ProtocolServerStreams
252
+ #connections: ProtocolConnections
253
+ #clientStreams: ProtocolClientStreams
254
+ #serverStreams: ProtocolServerStreams
222
255
 
223
256
  constructor(
224
257
  protected readonly application: {
@@ -229,18 +262,44 @@ export class Protocol {
229
262
  api: ProtocolApi
230
263
  },
231
264
  ) {
232
- this.connections = new ProtocolConnections(this.application)
233
- this.clientStreams = new ProtocolClientStreams(this.connections)
234
- this.serverStreams = new ProtocolServerStreams(this.connections)
265
+ this.#connections = new ProtocolConnections(this.application)
266
+ this.#clientStreams = new ProtocolClientStreams(this.#connections)
267
+ this.#serverStreams = new ProtocolServerStreams(this.#connections)
268
+ }
269
+
270
+ async call(options: ProtocolApiCallOptions) {
271
+ const { container, connection } = options
272
+ try {
273
+ return await this.application.api.call(options)
274
+ } catch (error) {
275
+ if (error instanceof ProtocolError === false) {
276
+ this.application.logger.error(
277
+ { error, connection },
278
+ 'Error during RPC call',
279
+ )
280
+ throw new ProtocolError(
281
+ ErrorCode.InternalServerError,
282
+ 'Internal server error',
283
+ )
284
+ }
285
+ throw error
286
+ } finally {
287
+ container.dispose().catch((error) => {
288
+ this.application.logger.error(
289
+ { error, connection },
290
+ "Error during disposing connection's container",
291
+ )
292
+ })
293
+ }
235
294
  }
236
295
 
237
296
  async rpc(
238
297
  connectionId: string,
239
298
  rpc: ProtocolRPC,
240
- params: { signal?: AbortSignal } = {},
299
+ params: ProtocolRPCOptions = {},
241
300
  ) {
242
301
  const { connection, context, transport } =
243
- this.connections.get(connectionId)
302
+ this.#connections.get(connectionId)
244
303
  const { calls, format } = context
245
304
  const { callId, namespace, procedure, payload } = rpc
246
305
  const abortController = new AbortController()
@@ -248,35 +307,37 @@ export class Protocol {
248
307
  ? AbortSignal.any([params.signal, abortController.signal])
249
308
  : abortController.signal
250
309
 
251
- const call = Object.assign(createPromise<ProtocolApiCallResult>(), {
252
- abort: () => abortController.abort(),
253
- })
254
-
255
- calls.set(callId, call)
256
- call.promise.finally(() => calls.delete(callId))
310
+ calls.set(callId, abortController)
257
311
 
258
312
  const callIdEncoded = encodeNumber(callId, 'Uint32')
259
313
  const container = context.container.fork(Scope.Call)
260
314
 
315
+ if (params.provides) {
316
+ for (const [key, value] of params.provides) {
317
+ container.provide(key, value)
318
+ }
319
+ }
320
+
261
321
  try {
262
- const response = await this.application.api.call({
322
+ const response = await this.call({
263
323
  connection,
264
324
  container,
265
325
  namespace,
266
326
  payload,
267
327
  procedure,
268
328
  signal,
329
+ metadata: params.metadata,
269
330
  })
270
331
 
271
332
  const responseEncoded = format.encoder.encodeRPC(
272
333
  {
273
334
  callId,
274
- payload: response.output,
335
+ result: response.output,
275
336
  },
276
337
  {
277
338
  addStream: (blob) => {
278
- const id = context.streamId++
279
- const stream = this.serverStreams.add(connectionId, id, blob)
339
+ const streamId = context.streamId++
340
+ const stream = this.#serverStreams.add(connectionId, streamId, blob)
280
341
  stream.on('data', (chunk) => {
281
342
  stream.pause()
282
343
  const buf = Buffer.from(chunk)
@@ -284,43 +345,48 @@ export class Protocol {
284
345
  connection,
285
346
  ServerMessageType.ServerStreamPush,
286
347
  concat(
287
- encodeNumber(id, 'Uint32'),
348
+ encodeNumber(streamId, 'Uint32'),
288
349
  (buf.buffer as ArrayBuffer).slice(
289
350
  buf.byteOffset,
290
351
  buf.byteOffset + buf.byteLength,
291
352
  ),
292
353
  ),
354
+ { callId, streamId },
293
355
  )
294
356
  })
295
357
  stream.on('error', (err) => {
296
358
  transport.send(
297
359
  connection,
298
360
  ServerMessageType.ServerStreamAbort,
299
- encodeNumber(id, 'Uint32'),
361
+ encodeNumber(streamId, 'Uint32'),
362
+ { callId, streamId },
300
363
  )
301
364
  })
302
365
  stream.on('end', () => {
366
+ console.log('Stream ended')
303
367
  transport.send(
304
368
  connection,
305
369
  ServerMessageType.ServerStreamEnd,
306
- encodeNumber(id, 'Uint32'),
370
+ encodeNumber(streamId, 'Uint32'),
371
+ { callId, streamId },
307
372
  )
308
373
  })
309
374
  return stream
310
375
  },
311
376
  getStream: (id) => {
312
- return this.clientStreams.get(connectionId, id)
377
+ return this.#serverStreams.get(connectionId, id)
313
378
  },
314
379
  },
315
380
  )
316
381
 
317
382
  if ('subscription' in response) {
318
383
  throwError('Unimplemented')
319
- } else if ('iterable' in response) {
384
+ } else if (isIterableResult(response)) {
320
385
  transport.send(
321
386
  connection,
322
387
  ServerMessageType.RpcStreamResponse,
323
388
  responseEncoded,
389
+ { callId },
324
390
  )
325
391
  try {
326
392
  const ab = new AbortController()
@@ -330,20 +396,28 @@ export class Protocol {
330
396
  ? response.iterable()
331
397
  : response.iterable
332
398
  for await (const chunk of iterable) {
333
- if (ab.signal.aborted) break
399
+ ab.signal.throwIfAborted()
334
400
  const chunkEncoded = format.encoder.encode(chunk)
335
401
  transport.send(
336
402
  connection,
337
403
  ServerMessageType.RpcStreamChunk,
338
404
  concat(callIdEncoded, chunkEncoded),
405
+ { callId },
339
406
  )
340
407
  }
408
+ transport.send(
409
+ connection,
410
+ ServerMessageType.RpcStreamEnd,
411
+ callIdEncoded,
412
+ { callId },
413
+ )
341
414
  } catch (error) {
342
415
  this.application.logger.error(error)
343
416
  transport.send(
344
417
  connection,
345
418
  ServerMessageType.RpcStreamAbort,
346
419
  callIdEncoded,
420
+ { callId },
347
421
  )
348
422
  } finally {
349
423
  context.rpcStreams.delete(callId)
@@ -354,22 +428,10 @@ export class Protocol {
354
428
  connection,
355
429
  ServerMessageType.RpcResponse,
356
430
  responseEncoded,
431
+ { callId },
357
432
  )
358
433
  }
359
434
  } catch (error) {
360
- if (error instanceof ProtocolError === false) {
361
- this.application.logger.error(
362
- { error, connection },
363
- 'Error during RPC call',
364
- )
365
-
366
- // biome-ignore lint/suspicious/noCatchAssign:
367
- error = new ProtocolError(
368
- ErrorCode.InternalServerError,
369
- 'Internal server error',
370
- )
371
- }
372
-
373
435
  const payload = format.encoder.encodeRPC(
374
436
  { callId, error },
375
437
  {
@@ -381,12 +443,17 @@ export class Protocol {
381
443
  },
382
444
  },
383
445
  )
384
- transport.send(connection, ServerMessageType.RpcResponse, payload)
446
+
447
+ transport.send(connection, ServerMessageType.RpcResponse, payload, {
448
+ error,
449
+ callId,
450
+ })
385
451
  } finally {
452
+ calls.delete(callId)
386
453
  container.dispose().catch((error) => {
387
454
  this.application.logger.error(
388
455
  { error, connection },
389
- "Error during disposing connection's container",
456
+ 'Error during disposing connection',
390
457
  )
391
458
  })
392
459
  }
@@ -395,31 +462,34 @@ export class Protocol {
395
462
  async rpcRaw(
396
463
  connectionId: string,
397
464
  buffer: ArrayBuffer,
398
- params: { signal?: AbortSignal } = {},
465
+ params: ProtocolRPCOptions = {},
399
466
  ) {
400
467
  const { connection, context, transport } =
401
- this.connections.get(connectionId)
468
+ this.#connections.get(connectionId)
402
469
 
403
470
  const { format } = context
404
471
 
405
472
  const rpc = format.decoder.decodeRPC(buffer, {
406
- addStream: (id, metadata) => {
407
- const stream = this.clientStreams.add(
473
+ addStream: (streamId, callId, metadata) => {
474
+ return this.#clientStreams.add(
408
475
  connectionId,
409
- id,
476
+ streamId,
410
477
  metadata,
411
478
  (size) => {
412
479
  transport.send(
413
480
  connection,
414
481
  ServerMessageType.ClientStreamPull,
415
- concat(encodeNumber(id, 'Uint32'), encodeNumber(size, 'Uint32')),
482
+ concat(
483
+ encodeNumber(streamId, 'Uint32'),
484
+ encodeNumber(size, 'Uint32'),
485
+ ),
486
+ { callId, streamId },
416
487
  )
417
488
  },
418
489
  )
419
- return stream
420
490
  },
421
491
  getStream: (id) => {
422
- return this.serverStreams.get(connectionId, id)
492
+ return this.#clientStreams.get(connectionId, id)
423
493
  },
424
494
  })
425
495
 
@@ -427,7 +497,7 @@ export class Protocol {
427
497
  }
428
498
 
429
499
  rpcAbort(connectionId: string, callId: number) {
430
- const { context } = this.connections.get(connectionId)
500
+ const { context } = this.#connections.get(connectionId)
431
501
  const call = context.calls.get(callId) ?? throwError('Call not found')
432
502
  call.abort()
433
503
  }
@@ -438,7 +508,7 @@ export class Protocol {
438
508
  }
439
509
 
440
510
  rpcStreamAbort(connectionId: string, callId: number) {
441
- const { context } = this.connections.get(connectionId)
511
+ const { context } = this.#connections.get(connectionId)
442
512
  const ab =
443
513
  context.rpcStreams.get(callId) ?? throwError('Call stream not found')
444
514
  ab.abort()
@@ -452,4 +522,76 @@ export class Protocol {
452
522
  notify(connectionId: string, event, payload) {
453
523
  throw Error('Unimplemented')
454
524
  }
525
+
526
+ addConnection(
527
+ transport: ProtocolConnectionTransport,
528
+ options: ConnectionOptions,
529
+ params: ResolveFormatParams,
530
+ ) {
531
+ return this.#connections.add(transport, options, params)
532
+ }
533
+
534
+ removeConnection(connectionId: string) {
535
+ return this.#connections.remove(connectionId)
536
+ }
537
+
538
+ getConnection(connectionId: string) {
539
+ return this.#connections.get(connectionId)
540
+ }
541
+
542
+ initializeConnection(connection: Connection) {
543
+ return this.#connections.initialize(connection)
544
+ }
545
+
546
+ getClientStream(
547
+ connectionId: string,
548
+ streamId: number,
549
+ ): ProtocolClientStream {
550
+ return this.#clientStreams.get(connectionId, streamId)
551
+ }
552
+
553
+ addClientStream(
554
+ connectionId: string,
555
+ streamId: number,
556
+ metadata: ProtocolBlobMetadata,
557
+ read: Callback,
558
+ ) {
559
+ return this.#clientStreams.add(connectionId, streamId, metadata, read)
560
+ }
561
+
562
+ removeClientStream(connectionId: string, streamId: number) {
563
+ return this.#clientStreams.remove(connectionId, streamId)
564
+ }
565
+
566
+ pushClientStream(connectionId: string, streamId: number, chunk: ArrayBuffer) {
567
+ return this.#clientStreams.push(connectionId, streamId, chunk)
568
+ }
569
+
570
+ endClientStream(connectionId: string, streamId: number) {
571
+ return this.#clientStreams.end(connectionId, streamId)
572
+ }
573
+
574
+ abortClientStream(connectionId: string, streamId: number, error?: Error) {
575
+ return this.#clientStreams.abort(connectionId, streamId, error)
576
+ }
577
+
578
+ getServerStream(connectionId: string, streamId: number) {
579
+ return this.#serverStreams.get(connectionId, streamId)
580
+ }
581
+
582
+ addServerStream(connectionId: string, streamId: number, blob: ProtocolBlob) {
583
+ return this.#serverStreams.add(connectionId, streamId, blob)
584
+ }
585
+
586
+ removeServerStream(connectionId: string, streamId: number) {
587
+ return this.#serverStreams.remove(connectionId, streamId)
588
+ }
589
+
590
+ pullServerStream(connectionId: string, streamId: number) {
591
+ return this.#serverStreams.pull(connectionId, streamId)
592
+ }
593
+
594
+ abortServerStream(connectionId: string, streamId: number, error?: Error) {
595
+ return this.#serverStreams.abort(connectionId, streamId, error)
596
+ }
455
597
  }
@@ -1,13 +1,8 @@
1
- import {
2
- PassThrough,
3
- Readable,
4
- type ReadableOptions,
5
- type TransformOptions,
6
- } from 'node:stream'
1
+ import { PassThrough, Readable, type ReadableOptions } from 'node:stream'
7
2
  import { ReadableStream } from 'node:stream/web'
8
3
  import type { ProtocolBlob, ProtocolBlobMetadata } from '../common/blob.ts'
9
4
 
10
- export class ProtocolClientStream extends Readable {
5
+ export class ProtocolClientStream extends PassThrough {
11
6
  constructor(
12
7
  public readonly id: number,
13
8
  public readonly metadata: ProtocolBlobMetadata,
@@ -3,8 +3,10 @@ import type { BasePlugin, PluginContext } from '@nmtjs/core'
3
3
  import type { ServerMessageType } from '../common/enums.ts'
4
4
  import type { Connection } from './connection.ts'
5
5
  import { kTransportPlugin } from './constants.ts'
6
+ import type { Format } from './format.ts'
6
7
  import type { Protocol } from './protocol.ts'
7
8
  import type { ProtocolRegistry } from './registry.ts'
9
+ import type { ProtocolSendMetadata } from './types.ts'
8
10
 
9
11
  export interface Transport<T = unknown> {
10
12
  start: () => Promise<void>
@@ -13,12 +15,14 @@ export interface Transport<T = unknown> {
13
15
  connection: Connection<T>,
14
16
  messageType: ServerMessageType,
15
17
  buffer: ArrayBuffer,
16
- ) => Async<void>
18
+ metadata: ProtocolSendMetadata,
19
+ ) => any
17
20
  }
18
21
 
19
22
  export interface TransportPluginContext extends PluginContext {
20
23
  protocol: Protocol
21
24
  registry: ProtocolRegistry
25
+ format: Format
22
26
  }
23
27
 
24
28
  export interface TransportPlugin<Type = unknown, Options = unknown>
@@ -0,0 +1,21 @@
1
+ import type { ProtocolServerBlobStream } from '../client/stream.ts'
2
+ import type { ProtocolBlob, ProtocolBlobInterface } from '../common/blob.ts'
3
+ import type { ProtocolClientStream } from './stream.ts'
4
+
5
+ export type InputType<T> = T extends ProtocolBlobInterface
6
+ ? ProtocolClientStream
7
+ : T extends object
8
+ ? { [K in keyof T]: InputType<T[K]> }
9
+ : T
10
+
11
+ export type OutputType<T> = T extends ProtocolBlobInterface
12
+ ? ProtocolBlob
13
+ : T extends object
14
+ ? { [K in keyof T]: OutputType<T[K]> }
15
+ : T
16
+
17
+ export type ProtocolSendMetadata = {
18
+ streamId?: number
19
+ callId?: number
20
+ error?: any
21
+ }
@@ -5,15 +5,22 @@ export type ResolveFormatParams = {
5
5
  acceptType?: string | null
6
6
  }
7
7
 
8
+ export class UnsupportedFormatError extends Error {}
9
+
10
+ export class UnsupportedContentTypeError extends UnsupportedFormatError {}
11
+
12
+ export class UnsupportedAcceptTypeError extends UnsupportedFormatError {}
13
+
8
14
  export const getFormat = (
9
15
  format: Format,
10
16
  { acceptType, contentType }: ResolveFormatParams,
11
17
  ) => {
12
18
  const encoder = contentType ? format.supportsEncoder(contentType) : undefined
13
- if (!encoder) throw new Error('Unsupported content-type')
19
+ if (!encoder)
20
+ throw new UnsupportedContentTypeError('Unsupported Content-Type')
14
21
 
15
22
  const decoder = acceptType ? format.supportsDecoder(acceptType) : undefined
16
- if (!decoder) throw new Error('Unsupported accept')
23
+ if (!decoder) throw new UnsupportedAcceptTypeError('Unsupported Accept-Type')
17
24
 
18
25
  return {
19
26
  encoder,