@flighthq/image-codec 0.5.1-next.1556.ff9e615 → 0.5.1-next.1629.669e7c5

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 (40) hide show
  1. package/README.md +2 -2
  2. package/dist/contract.d.ts +0 -4
  3. package/dist/contract.d.ts.map +1 -1
  4. package/dist/contract.js +0 -4
  5. package/dist/contract.js.map +1 -1
  6. package/dist/decodeImage.d.ts +3 -3
  7. package/dist/decodeImage.d.ts.map +1 -1
  8. package/dist/decodeImage.js +28 -16
  9. package/dist/decodeImage.js.map +1 -1
  10. package/dist/encodeImage.d.ts +2 -2
  11. package/dist/encodeImage.d.ts.map +1 -1
  12. package/dist/encodeImage.js +16 -7
  13. package/dist/encodeImage.js.map +1 -1
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -1
  17. package/dist/index.js.map +1 -1
  18. package/package.json +2 -2
  19. package/src/decodeImage.test.ts +36 -35
  20. package/src/encodeImage.test.ts +20 -17
  21. package/dist/explainImageDecodeFailure.d.ts +0 -3
  22. package/dist/explainImageDecodeFailure.d.ts.map +0 -1
  23. package/dist/explainImageDecodeFailure.js +0 -13
  24. package/dist/explainImageDecodeFailure.js.map +0 -1
  25. package/dist/explainImageEncodeFailure.d.ts +0 -3
  26. package/dist/explainImageEncodeFailure.d.ts.map +0 -1
  27. package/dist/explainImageEncodeFailure.js +0 -9
  28. package/dist/explainImageEncodeFailure.js.map +0 -1
  29. package/dist/imageDecoderRegistry.d.ts +0 -8
  30. package/dist/imageDecoderRegistry.d.ts.map +0 -1
  31. package/dist/imageDecoderRegistry.js +0 -25
  32. package/dist/imageDecoderRegistry.js.map +0 -1
  33. package/dist/imageEncoderRegistry.d.ts +0 -8
  34. package/dist/imageEncoderRegistry.d.ts.map +0 -1
  35. package/dist/imageEncoderRegistry.js +0 -25
  36. package/dist/imageEncoderRegistry.js.map +0 -1
  37. package/src/explainImageDecodeFailure.test.ts +0 -37
  38. package/src/explainImageEncodeFailure.test.ts +0 -24
  39. package/src/imageDecoderRegistry.test.ts +0 -84
  40. package/src/imageEncoderRegistry.test.ts +0 -80
package/README.md CHANGED
@@ -13,5 +13,5 @@ Import the supported application-facing API from `@flighthq/image-codec`. The `@
13
13
  This package is part of the locked-version Flight SDK graph. Applications may instead install and import `@flighthq/sdk` when package-level tree shaking is sufficient.
14
14
 
15
15
  - [Flight project](https://github.com/flighthq/flight)
16
- - [Source for @flighthq/image-codec@0.5.1-next.1556.ff9e615](https://github.com/flighthq/flight/tree/ff9e615c3b9df79b718bc750dc04e1cb5f39e5cd/packages/image-codec)
17
- - [License](https://github.com/flighthq/flight/blob/ff9e615c3b9df79b718bc750dc04e1cb5f39e5cd/LICENSE.md)
16
+ - [Source for @flighthq/image-codec@0.5.1-next.1629.669e7c5](https://github.com/flighthq/flight/tree/669e7c57b5177f4dba43dd9e861db543c4d72d2d/packages/image-codec)
17
+ - [License](https://github.com/flighthq/flight/blob/669e7c57b5177f4dba43dd9e861db543c4d72d2d/LICENSE.md)
@@ -1,8 +1,4 @@
1
1
  export * from './decodeImage';
2
2
  export * from './detectImageMimeType';
3
3
  export * from './encodeImage';
4
- export * from './explainImageDecodeFailure';
5
- export * from './explainImageEncodeFailure';
6
- export * from './imageDecoderRegistry';
7
- export * from './imageEncoderRegistry';
8
4
  //# sourceMappingURL=contract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC"}
package/dist/contract.js CHANGED
@@ -1,8 +1,4 @@
1
1
  export * from './decodeImage';
2
2
  export * from './detectImageMimeType';
3
3
  export * from './encodeImage';
4
- export * from './explainImageDecodeFailure';
5
- export * from './explainImageEncodeFailure';
6
- export * from './imageDecoderRegistry';
7
- export * from './imageEncoderRegistry';
8
4
  //# sourceMappingURL=contract.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC"}
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { DecodedImage } from '@flighthq/types/contract';
2
- export declare function decodeImage(bytes: Readonly<Uint8Array>, mimeType?: string): Promise<DecodedImage | null>;
3
- export declare function decodeImagePremultiplied(bytes: Readonly<Uint8Array>, mimeType?: string): Promise<DecodedImage | null>;
1
+ import type { DecodedImage, HostImageDecodeCapabilities } from '@flighthq/types/contract';
2
+ export declare function decodeImage(imageDecode: Readonly<HostImageDecodeCapabilities>, bytes: Readonly<Uint8Array>, mimeType?: string): Promise<DecodedImage | null>;
3
+ export declare function decodeImagePremultiplied(imageDecode: Readonly<HostImageDecodeCapabilities>, bytes: Readonly<Uint8Array>, mimeType?: string): Promise<DecodedImage | null>;
4
4
  //# sourceMappingURL=decodeImage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decodeImage.d.ts","sourceRoot":"","sources":["../src/decodeImage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,0BAA0B,CAAC;AAQ3E,wBAAsB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAI9G;AAID,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC3B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAI9B"}
1
+ {"version":3,"file":"decodeImage.d.ts","sourceRoot":"","sources":["../src/decodeImage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,2BAA2B,EAE5B,MAAM,0BAA0B,CAAC;AAIlC,wBAAsB,WAAW,CAC/B,WAAW,EAAE,QAAQ,CAAC,2BAA2B,CAAC,EAClD,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC3B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAI9B;AAED,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,QAAQ,CAAC,2BAA2B,CAAC,EAClD,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC3B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAI9B"}
@@ -1,26 +1,38 @@
1
1
  import { detectImageMimeType } from './detectImageMimeType';
2
- import { getImageDecoder } from './imageDecoderRegistry';
3
- // Decodes encoded image bytes to straight (non-premultiplied) RGBA. Resolves the MIME type via
4
- // detectImageMimeType when mimeType is omitted, then dispatches to the registered decoder. Returns null
5
- // when the type cannot be determined or no decoder is registered for it.
6
- export async function decodeImage(bytes, mimeType) {
7
- const decoder = resolveImageDecoder(bytes, mimeType);
8
- if (decoder === null)
2
+ export async function decodeImage(imageDecode, bytes, mimeType) {
3
+ const slot = resolveDecodeSlot(imageDecode, bytes, mimeType);
4
+ if (slot === null)
9
5
  return null;
10
- return decoder(bytes);
6
+ return slot.decode(bytes);
11
7
  }
12
- // As decodeImage, but requests premultiplied RGBA via the decoder's premultiplyAlpha option. A decoder
13
- // that can premultiply in one pass does so; the web/canvas decoder falls back to a JS premultiply pass.
14
- export async function decodeImagePremultiplied(bytes, mimeType) {
15
- const decoder = resolveImageDecoder(bytes, mimeType);
16
- if (decoder === null)
8
+ export async function decodeImagePremultiplied(imageDecode, bytes, mimeType) {
9
+ const slot = resolveDecodeSlot(imageDecode, bytes, mimeType);
10
+ if (slot === null)
17
11
  return null;
18
- return decoder(bytes, { premultiplyAlpha: true });
12
+ return slot.decode(bytes, { premultiplyAlpha: true });
19
13
  }
20
- function resolveImageDecoder(bytes, mimeType) {
14
+ function resolveDecodeSlot(imageDecode, bytes, mimeType) {
21
15
  const type = mimeType ?? detectImageMimeType(bytes);
22
16
  if (type === null)
23
17
  return null;
24
- return getImageDecoder(type);
18
+ return getImageDecodeSlot(imageDecode, type);
19
+ }
20
+ function getImageDecodeSlot(imageDecode, mimeType) {
21
+ switch (mimeType) {
22
+ case 'image/avif':
23
+ return imageDecode.avif ?? null;
24
+ case 'image/bmp':
25
+ return imageDecode.bmp ?? null;
26
+ case 'image/gif':
27
+ return imageDecode.gif ?? null;
28
+ case 'image/jpeg':
29
+ return imageDecode.jpeg ?? null;
30
+ case 'image/png':
31
+ return imageDecode.png ?? null;
32
+ case 'image/webp':
33
+ return imageDecode.webp ?? null;
34
+ default:
35
+ return null;
36
+ }
25
37
  }
26
38
  //# sourceMappingURL=decodeImage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"decodeImage.js","sourceRoot":"","sources":["../src/decodeImage.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,+FAA+F;AAC/F,wGAAwG;AACxG,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAA2B,EAAE,QAAiB;IAC9E,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrD,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAClC,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC;AAED,uGAAuG;AACvG,wGAAwG;AACxG,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,KAA2B,EAC3B,QAAiB;IAEjB,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrD,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAClC,OAAO,OAAO,CAAC,KAAK,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,mBAAmB,CAAC,KAA2B,EAAE,QAAiB;IACzE,MAAM,IAAI,GAAG,QAAQ,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC"}
1
+ {"version":3,"file":"decodeImage.js","sourceRoot":"","sources":["../src/decodeImage.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,WAAkD,EAClD,KAA2B,EAC3B,QAAiB;IAEjB,MAAM,IAAI,GAAG,iBAAiB,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC7D,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,WAAkD,EAClD,KAA2B,EAC3B,QAAiB;IAEjB,MAAM,IAAI,GAAG,iBAAiB,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC7D,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,iBAAiB,CACxB,WAAkD,EAClD,KAA2B,EAC3B,QAAiB;IAEjB,MAAM,IAAI,GAAG,QAAQ,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,OAAO,kBAAkB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,kBAAkB,CACzB,WAAkD,EAClD,QAAgB;IAEhB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,YAAY;YACf,OAAO,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC;QAClC,KAAK,WAAW;YACd,OAAO,WAAW,CAAC,GAAG,IAAI,IAAI,CAAC;QACjC,KAAK,WAAW;YACd,OAAO,WAAW,CAAC,GAAG,IAAI,IAAI,CAAC;QACjC,KAAK,YAAY;YACf,OAAO,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC;QAClC,KAAK,WAAW;YACd,OAAO,WAAW,CAAC,GAAG,IAAI,IAAI,CAAC;QACjC,KAAK,YAAY;YACf,OAAO,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC;QAClC;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -1,3 +1,3 @@
1
- import type { DecodedImage, ImageEncodeOptions } from '@flighthq/types/contract';
2
- export declare function encodeImage(image: Readonly<DecodedImage>, mimeType: string, options?: Readonly<ImageEncodeOptions>): Promise<Uint8Array | null>;
1
+ import type { DecodedImage, HostImageEncodeCapabilities, ImageEncodeOptions } from '@flighthq/types/contract';
2
+ export declare function encodeImage(imageEncode: Readonly<HostImageEncodeCapabilities>, image: Readonly<DecodedImage>, mimeType: string, options?: Readonly<ImageEncodeOptions>): Promise<Uint8Array | null>;
3
3
  //# sourceMappingURL=encodeImage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"encodeImage.d.ts","sourceRoot":"","sources":["../src/encodeImage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAMjF,wBAAsB,WAAW,CAC/B,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,QAAQ,CAAC,kBAAkB,CAAC,GACrC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAI5B"}
1
+ {"version":3,"file":"encodeImage.d.ts","sourceRoot":"","sources":["../src/encodeImage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,2BAA2B,EAE3B,kBAAkB,EACnB,MAAM,0BAA0B,CAAC;AAElC,wBAAsB,WAAW,CAC/B,WAAW,EAAE,QAAQ,CAAC,2BAA2B,CAAC,EAClD,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,EAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,QAAQ,CAAC,kBAAkB,CAAC,GACrC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAI5B"}
@@ -1,10 +1,19 @@
1
- import { getImageEncoder } from './imageEncoderRegistry';
2
- // Encodes raw RGBA pixels to bytes of the given MIME type via the registered encoder. Returns null when
3
- // no encoder is registered for the type.
4
- export async function encodeImage(image, mimeType, options) {
5
- const encoder = getImageEncoder(mimeType);
6
- if (encoder === null)
1
+ export async function encodeImage(imageEncode, image, mimeType, options) {
2
+ const slot = getImageEncodeSlot(imageEncode, mimeType);
3
+ if (slot === null)
7
4
  return null;
8
- return encoder(image, options);
5
+ return slot.encode(image, options);
6
+ }
7
+ function getImageEncodeSlot(imageEncode, mimeType) {
8
+ switch (mimeType) {
9
+ case 'image/jpeg':
10
+ return imageEncode.jpeg ?? null;
11
+ case 'image/png':
12
+ return imageEncode.png ?? null;
13
+ case 'image/webp':
14
+ return imageEncode.webp ?? null;
15
+ default:
16
+ return null;
17
+ }
9
18
  }
10
19
  //# sourceMappingURL=encodeImage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"encodeImage.js","sourceRoot":"","sources":["../src/encodeImage.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,wGAAwG;AACxG,yCAAyC;AACzC,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAA6B,EAC7B,QAAgB,EAChB,OAAsC;IAEtC,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAClC,OAAO,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"encodeImage.js","sourceRoot":"","sources":["../src/encodeImage.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,WAAkD,EAClD,KAA6B,EAC7B,QAAgB,EAChB,OAAsC;IAEtC,MAAM,IAAI,GAAG,kBAAkB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACvD,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,kBAAkB,CACzB,WAAkD,EAClD,QAAgB;IAEhB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,YAAY;YACf,OAAO,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC;QAClC,KAAK,WAAW;YACd,OAAO,WAAW,CAAC,GAAG,IAAI,IAAI,CAAC;QACjC,KAAK,YAAY;YACf,OAAO,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC;QAClC;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { clearImageDecoders, clearImageEncoders, decodeImage, decodeImagePremultiplied, detectImageMimeType, encodeImage, explainImageDecodeFailure, explainImageEncodeFailure, getImageDecoder, getImageDecoderMimeTypes, getImageEncoder, getImageEncoderMimeTypes, hasImageDecoder, hasImageEncoder, registerImageDecoder, registerImageEncoder, unregisterImageDecoder, unregisterImageEncoder, } from './contract';
1
+ export { decodeImage, decodeImagePremultiplied, detectImageMimeType, encodeImage } from './contract';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,wBAAwB,EACxB,mBAAmB,EACnB,WAAW,EACX,yBAAyB,EACzB,yBAAyB,EACzB,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { clearImageDecoders, clearImageEncoders, decodeImage, decodeImagePremultiplied, detectImageMimeType, encodeImage, explainImageDecodeFailure, explainImageEncodeFailure, getImageDecoder, getImageDecoderMimeTypes, getImageEncoder, getImageEncoderMimeTypes, hasImageDecoder, hasImageEncoder, registerImageDecoder, registerImageEncoder, unregisterImageDecoder, unregisterImageEncoder, } from './contract';
1
+ export { decodeImage, decodeImagePremultiplied, detectImageMimeType, encodeImage } from './contract';
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,wBAAwB,EACxB,mBAAmB,EACnB,WAAW,EACX,yBAAyB,EACzB,yBAAyB,EACzB,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/image-codec",
3
- "version": "0.5.1-next.1556.ff9e615",
3
+ "version": "0.5.1-next.1629.669e7c5",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,7 +38,7 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/types": "0.5.1-next.1556.ff9e615"
41
+ "@flighthq/types": "0.5.1-next.1629.669e7c5"
42
42
  },
43
43
  "devDependencies": {
44
44
  "typescript": "^5.3.0"
@@ -1,70 +1,71 @@
1
- import type { DecodedImage, ImageDecodeOptions } from '@flighthq/types/contract';
1
+ import type {
2
+ DecodedImage,
3
+ HostImageDecodeCapabilities,
4
+ HostImageDecodeFormatCapability,
5
+ } from '@flighthq/types/contract';
2
6
  import { vi } from 'vitest';
3
7
 
4
8
  import { decodeImage, decodeImagePremultiplied } from './decodeImage';
5
- import { clearImageDecoders, registerImageDecoder } from './imageDecoderRegistry';
6
9
 
7
- // PNG magic bytes so the omitted-mimeType path resolves through detectImageMimeType.
8
10
  const pngBytes = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
9
11
 
10
12
  function fakeDecoded(): DecodedImage {
11
13
  return { data: new Uint8ClampedArray([1, 2, 3, 4]), width: 1, height: 1 };
12
14
  }
13
15
 
14
- afterEach(() => {
15
- clearImageDecoders();
16
- });
16
+ function fakeSlot(): HostImageDecodeFormatCapability {
17
+ return { decode: vi.fn(async () => fakeDecoded()) };
18
+ }
17
19
 
18
20
  describe('decodeImage', () => {
19
- it('auto-detects the MIME type when omitted and dispatches to the registered decoder', async () => {
20
- const decoder = vi.fn(async () => fakeDecoded());
21
- registerImageDecoder('image/png', decoder);
22
- const result = await decodeImage(pngBytes);
21
+ it('auto-detects the MIME type when omitted and dispatches to the capability slot', async () => {
22
+ const slot = fakeSlot();
23
+ const caps: HostImageDecodeCapabilities = { png: slot };
24
+ const result = await decodeImage(caps, pngBytes);
23
25
  expect(result).toEqual(fakeDecoded());
24
- expect(decoder).toHaveBeenCalledWith(pngBytes);
26
+ expect(slot.decode).toHaveBeenCalledWith(pngBytes);
25
27
  });
26
28
 
27
29
  it('uses an explicit MIME type over detection', async () => {
28
- const decoder = vi.fn(async () => fakeDecoded());
29
- registerImageDecoder('image/jpeg', decoder);
30
- await decodeImage(pngBytes, 'image/jpeg');
31
- expect(decoder).toHaveBeenCalledOnce();
30
+ const slot = fakeSlot();
31
+ const caps: HostImageDecodeCapabilities = { jpeg: slot };
32
+ await decodeImage(caps, pngBytes, 'image/jpeg');
33
+ expect(slot.decode).toHaveBeenCalledOnce();
32
34
  });
33
35
 
34
- it('returns null when no decoder is registered', async () => {
35
- expect(await decodeImage(pngBytes)).toBeNull();
36
+ it('returns null when no slot is present for the detected type', async () => {
37
+ expect(await decodeImage({}, pngBytes)).toBeNull();
36
38
  });
37
39
 
38
40
  it('returns null when the MIME type cannot be determined', async () => {
39
- expect(await decodeImage(new Uint8Array([0, 1, 2, 3]))).toBeNull();
41
+ const caps: HostImageDecodeCapabilities = { png: fakeSlot() };
42
+ expect(await decodeImage(caps, new Uint8Array([0, 1, 2, 3]))).toBeNull();
40
43
  });
41
44
 
42
45
  it('does not request premultiplied output', async () => {
43
- const decoder = vi.fn(async () => fakeDecoded());
44
- registerImageDecoder('image/png', decoder);
45
- await decodeImage(pngBytes);
46
- expect(decoder).toHaveBeenCalledWith(pngBytes);
46
+ const slot = fakeSlot();
47
+ const caps: HostImageDecodeCapabilities = { png: slot };
48
+ await decodeImage(caps, pngBytes);
49
+ expect(slot.decode).toHaveBeenCalledWith(pngBytes);
47
50
  });
48
51
  });
49
52
 
50
53
  describe('decodeImagePremultiplied', () => {
51
- it('passes premultiplyAlpha true to the decoder', async () => {
52
- const decoder = vi.fn(async (_bytes: Readonly<Uint8Array>, _options?: Readonly<ImageDecodeOptions>) =>
53
- fakeDecoded(),
54
- );
55
- registerImageDecoder('image/png', decoder);
56
- await decodeImagePremultiplied(pngBytes, 'image/png');
57
- expect(decoder).toHaveBeenCalledWith(pngBytes, { premultiplyAlpha: true });
54
+ it('passes premultiplyAlpha true to the slot', async () => {
55
+ const slot = fakeSlot();
56
+ const caps: HostImageDecodeCapabilities = { png: slot };
57
+ await decodeImagePremultiplied(caps, pngBytes, 'image/png');
58
+ expect(slot.decode).toHaveBeenCalledWith(pngBytes, { premultiplyAlpha: true });
58
59
  });
59
60
 
60
61
  it('auto-detects the MIME type when omitted', async () => {
61
- const decoder = vi.fn(async () => fakeDecoded());
62
- registerImageDecoder('image/png', decoder);
63
- expect(await decodeImagePremultiplied(pngBytes)).toEqual(fakeDecoded());
64
- expect(decoder).toHaveBeenCalledWith(pngBytes, { premultiplyAlpha: true });
62
+ const slot = fakeSlot();
63
+ const caps: HostImageDecodeCapabilities = { png: slot };
64
+ expect(await decodeImagePremultiplied(caps, pngBytes)).toEqual(fakeDecoded());
65
+ expect(slot.decode).toHaveBeenCalledWith(pngBytes, { premultiplyAlpha: true });
65
66
  });
66
67
 
67
- it('returns null when no decoder is registered', async () => {
68
- expect(await decodeImagePremultiplied(pngBytes)).toBeNull();
68
+ it('returns null when no slot is present for the detected type', async () => {
69
+ expect(await decodeImagePremultiplied({}, pngBytes)).toBeNull();
69
70
  });
70
71
  });
@@ -1,37 +1,40 @@
1
- import type { DecodedImage } from '@flighthq/types/contract';
1
+ import type {
2
+ DecodedImage,
3
+ HostImageEncodeCapabilities,
4
+ HostImageEncodeFormatCapability,
5
+ } from '@flighthq/types/contract';
2
6
  import { vi } from 'vitest';
3
7
 
4
8
  import { encodeImage } from './encodeImage';
5
- import { clearImageEncoders, registerImageEncoder } from './imageEncoderRegistry';
6
9
 
7
10
  function fakeImage(): DecodedImage {
8
11
  return { data: new Uint8ClampedArray([1, 2, 3, 4]), width: 1, height: 1 };
9
12
  }
10
13
 
11
- afterEach(() => {
12
- clearImageEncoders();
13
- });
14
+ function fakeSlot(result: Uint8Array = new Uint8Array(0)): HostImageEncodeFormatCapability {
15
+ return { encode: vi.fn(async () => result) };
16
+ }
14
17
 
15
18
  describe('encodeImage', () => {
16
- it('dispatches to the registered encoder and returns its bytes', async () => {
19
+ it('dispatches to the capability slot and returns its bytes', async () => {
17
20
  const bytes = new Uint8Array([9, 8, 7]);
18
- const encoder = vi.fn(async () => bytes);
19
- registerImageEncoder('image/png', encoder);
21
+ const slot = fakeSlot(bytes);
22
+ const caps: HostImageEncodeCapabilities = { png: slot };
20
23
  const image = fakeImage();
21
- const result = await encodeImage(image, 'image/png');
24
+ const result = await encodeImage(caps, image, 'image/png');
22
25
  expect(result).toBe(bytes);
23
- expect(encoder).toHaveBeenCalledWith(image, undefined);
26
+ expect(slot.encode).toHaveBeenCalledWith(image, undefined);
24
27
  });
25
28
 
26
- it('forwards encode options to the encoder', async () => {
27
- const encoder = vi.fn(async () => new Uint8Array(0));
28
- registerImageEncoder('image/jpeg', encoder);
29
+ it('forwards encode options to the slot', async () => {
30
+ const slot = fakeSlot();
31
+ const caps: HostImageEncodeCapabilities = { jpeg: slot };
29
32
  const image = fakeImage();
30
- await encodeImage(image, 'image/jpeg', { quality: 0.5 });
31
- expect(encoder).toHaveBeenCalledWith(image, { quality: 0.5 });
33
+ await encodeImage(caps, image, 'image/jpeg', { quality: 0.5 });
34
+ expect(slot.encode).toHaveBeenCalledWith(image, { quality: 0.5 });
32
35
  });
33
36
 
34
- it('returns null when no encoder is registered', async () => {
35
- expect(await encodeImage(fakeImage(), 'image/png')).toBeNull();
37
+ it('returns null when no slot is present for the MIME type', async () => {
38
+ expect(await encodeImage({}, fakeImage(), 'image/png')).toBeNull();
36
39
  });
37
40
  });
@@ -1,3 +0,0 @@
1
- import type { ImageDecodeFailureExplanation } from '@flighthq/types/contract';
2
- export declare function explainImageDecodeFailure(bytes: Readonly<Uint8Array>, mimeType?: string): ImageDecodeFailureExplanation | null;
3
- //# sourceMappingURL=explainImageDecodeFailure.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"explainImageDecodeFailure.d.ts","sourceRoot":"","sources":["../src/explainImageDecodeFailure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AAO9E,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC3B,QAAQ,CAAC,EAAE,MAAM,GAChB,6BAA6B,GAAG,IAAI,CAKtC"}
@@ -1,13 +0,0 @@
1
- import { detectImageMimeType } from './detectImageMimeType';
2
- import { getImageDecoder } from './imageDecoderRegistry';
3
- // Explains the two dispatcher failures that decodeImage represents with null. Returns null when the
4
- // same request can reach a registered decoder. This is a read-only query and never invokes the codec.
5
- export function explainImageDecodeFailure(bytes, mimeType) {
6
- const type = mimeType ?? detectImageMimeType(bytes);
7
- if (type === null)
8
- return { mimeType: null, reason: 'mime-type-undetected' };
9
- if (getImageDecoder(type) === null)
10
- return { mimeType: type, reason: 'decoder-not-registered' };
11
- return null;
12
- }
13
- //# sourceMappingURL=explainImageDecodeFailure.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"explainImageDecodeFailure.js","sourceRoot":"","sources":["../src/explainImageDecodeFailure.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,oGAAoG;AACpG,sGAAsG;AACtG,MAAM,UAAU,yBAAyB,CACvC,KAA2B,EAC3B,QAAiB;IAEjB,MAAM,IAAI,GAAG,QAAQ,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;IAC7E,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC;IAChG,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { ImageEncodeFailureExplanation } from '@flighthq/types/contract';
2
- export declare function explainImageEncodeFailure(mimeType: string): ImageEncodeFailureExplanation | null;
3
- //# sourceMappingURL=explainImageEncodeFailure.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"explainImageEncodeFailure.d.ts","sourceRoot":"","sources":["../src/explainImageEncodeFailure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AAM9E,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,6BAA6B,GAAG,IAAI,CAGhG"}
@@ -1,9 +0,0 @@
1
- import { getImageEncoder } from './imageEncoderRegistry';
2
- // Explains the dispatcher failure that encodeImage represents with null. Returns null when an encoder
3
- // is registered for the requested MIME type. This is a read-only query and never invokes the codec.
4
- export function explainImageEncodeFailure(mimeType) {
5
- if (getImageEncoder(mimeType) !== null)
6
- return null;
7
- return { mimeType, reason: 'encoder-not-registered' };
8
- }
9
- //# sourceMappingURL=explainImageEncodeFailure.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"explainImageEncodeFailure.js","sourceRoot":"","sources":["../src/explainImageEncodeFailure.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,sGAAsG;AACtG,oGAAoG;AACpG,MAAM,UAAU,yBAAyB,CAAC,QAAgB;IACxD,IAAI,eAAe,CAAC,QAAQ,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC;AACxD,CAAC"}
@@ -1,8 +0,0 @@
1
- import type { ImageDecoder } from '@flighthq/types/contract';
2
- export declare function clearImageDecoders(): void;
3
- export declare function getImageDecoder(mimeType: string): ImageDecoder | null;
4
- export declare function getImageDecoderMimeTypes(): readonly string[];
5
- export declare function hasImageDecoder(mimeType: string): boolean;
6
- export declare function registerImageDecoder(mimeType: string, decoder: ImageDecoder): void;
7
- export declare function unregisterImageDecoder(mimeType: string): void;
8
- //# sourceMappingURL=imageDecoderRegistry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"imageDecoderRegistry.d.ts","sourceRoot":"","sources":["../src/imageDecoderRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAErE;AAID,wBAAgB,wBAAwB,IAAI,SAAS,MAAM,EAAE,CAE5D;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAElF;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE7D"}
@@ -1,25 +0,0 @@
1
- export function clearImageDecoders() {
2
- decoders.clear();
3
- }
4
- export function getImageDecoder(mimeType) {
5
- return decoders.get(mimeType) ?? null;
6
- }
7
- // Returns an insertion-ordered snapshot of the MIME types with registered decoders. Mutating the
8
- // returned array cannot change registry state.
9
- export function getImageDecoderMimeTypes() {
10
- return Array.from(decoders.keys());
11
- }
12
- export function hasImageDecoder(mimeType) {
13
- return decoders.has(mimeType);
14
- }
15
- export function registerImageDecoder(mimeType, decoder) {
16
- decoders.set(mimeType, decoder);
17
- }
18
- export function unregisterImageDecoder(mimeType) {
19
- decoders.delete(mimeType);
20
- }
21
- // Global MIME-keyed decoder registry. Empty at import — only register* populates it, so importing this
22
- // package has no side effects. Last-write-wins: a native host can override the web decoder for a MIME
23
- // type by registering after registerWebImageDecoders.
24
- const decoders = new Map();
25
- //# sourceMappingURL=imageDecoderRegistry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"imageDecoderRegistry.js","sourceRoot":"","sources":["../src/imageDecoderRegistry.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB;IAChC,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,OAAO,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAED,iGAAiG;AACjG,+CAA+C;AAC/C,MAAM,UAAU,wBAAwB;IACtC,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,OAAO,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,OAAqB;IAC1E,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC5B,CAAC;AAED,uGAAuG;AACvG,sGAAsG;AACtG,sDAAsD;AACtD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC"}
@@ -1,8 +0,0 @@
1
- import type { ImageEncoder } from '@flighthq/types/contract';
2
- export declare function clearImageEncoders(): void;
3
- export declare function getImageEncoder(mimeType: string): ImageEncoder | null;
4
- export declare function getImageEncoderMimeTypes(): readonly string[];
5
- export declare function hasImageEncoder(mimeType: string): boolean;
6
- export declare function registerImageEncoder(mimeType: string, encoder: ImageEncoder): void;
7
- export declare function unregisterImageEncoder(mimeType: string): void;
8
- //# sourceMappingURL=imageEncoderRegistry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"imageEncoderRegistry.d.ts","sourceRoot":"","sources":["../src/imageEncoderRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAErE;AAID,wBAAgB,wBAAwB,IAAI,SAAS,MAAM,EAAE,CAE5D;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAElF;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE7D"}
@@ -1,25 +0,0 @@
1
- export function clearImageEncoders() {
2
- encoders.clear();
3
- }
4
- export function getImageEncoder(mimeType) {
5
- return encoders.get(mimeType) ?? null;
6
- }
7
- // Returns an insertion-ordered snapshot of the MIME types with registered encoders. Mutating the
8
- // returned array cannot change registry state.
9
- export function getImageEncoderMimeTypes() {
10
- return Array.from(encoders.keys());
11
- }
12
- export function hasImageEncoder(mimeType) {
13
- return encoders.has(mimeType);
14
- }
15
- export function registerImageEncoder(mimeType, encoder) {
16
- encoders.set(mimeType, encoder);
17
- }
18
- export function unregisterImageEncoder(mimeType) {
19
- encoders.delete(mimeType);
20
- }
21
- // Global MIME-keyed encoder registry. Empty at import — only register* populates it, so importing this
22
- // package has no side effects. Last-write-wins: a native host can override the web encoder for a MIME
23
- // type by registering after registerWebImageEncoders.
24
- const encoders = new Map();
25
- //# sourceMappingURL=imageEncoderRegistry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"imageEncoderRegistry.js","sourceRoot":"","sources":["../src/imageEncoderRegistry.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB;IAChC,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,OAAO,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAED,iGAAiG;AACjG,+CAA+C;AAC/C,MAAM,UAAU,wBAAwB;IACtC,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,OAAO,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,OAAqB;IAC1E,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC5B,CAAC;AAED,uGAAuG;AACvG,sGAAsG;AACtG,sDAAsD;AACtD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC"}
@@ -1,37 +0,0 @@
1
- import { vi } from 'vitest';
2
-
3
- import { explainImageDecodeFailure } from './explainImageDecodeFailure';
4
- import { clearImageDecoders, registerImageDecoder } from './imageDecoderRegistry';
5
-
6
- const pngBytes = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
7
-
8
- afterEach(() => {
9
- clearImageDecoders();
10
- });
11
-
12
- describe('explainImageDecodeFailure', () => {
13
- it('distinguishes an undetected MIME type from a missing decoder', () => {
14
- expect(explainImageDecodeFailure(new Uint8Array([0, 1, 2, 3]))).toEqual({
15
- mimeType: null,
16
- reason: 'mime-type-undetected',
17
- });
18
- expect(explainImageDecodeFailure(pngBytes)).toEqual({
19
- mimeType: 'image/png',
20
- reason: 'decoder-not-registered',
21
- });
22
- });
23
-
24
- it('reports the explicit MIME type when its decoder is missing', () => {
25
- expect(explainImageDecodeFailure(pngBytes, 'image/custom')).toEqual({
26
- mimeType: 'image/custom',
27
- reason: 'decoder-not-registered',
28
- });
29
- });
30
-
31
- it('returns null without invoking a registered decoder', () => {
32
- const decoder = vi.fn();
33
- registerImageDecoder('image/png', decoder);
34
- expect(explainImageDecodeFailure(pngBytes)).toBeNull();
35
- expect(decoder).not.toHaveBeenCalled();
36
- });
37
- });
@@ -1,24 +0,0 @@
1
- import { vi } from 'vitest';
2
-
3
- import { explainImageEncodeFailure } from './explainImageEncodeFailure';
4
- import { clearImageEncoders, registerImageEncoder } from './imageEncoderRegistry';
5
-
6
- afterEach(() => {
7
- clearImageEncoders();
8
- });
9
-
10
- describe('explainImageEncodeFailure', () => {
11
- it('reports a missing encoder and its requested MIME type', () => {
12
- expect(explainImageEncodeFailure('image/custom')).toEqual({
13
- mimeType: 'image/custom',
14
- reason: 'encoder-not-registered',
15
- });
16
- });
17
-
18
- it('returns null without invoking a registered encoder', () => {
19
- const encoder = vi.fn();
20
- registerImageEncoder('image/png', encoder);
21
- expect(explainImageEncodeFailure('image/png')).toBeNull();
22
- expect(encoder).not.toHaveBeenCalled();
23
- });
24
- });
@@ -1,84 +0,0 @@
1
- import type { DecodedImage, ImageDecoder } from '@flighthq/types/contract';
2
-
3
- import {
4
- clearImageDecoders,
5
- getImageDecoder,
6
- getImageDecoderMimeTypes,
7
- hasImageDecoder,
8
- registerImageDecoder,
9
- unregisterImageDecoder,
10
- } from './imageDecoderRegistry';
11
-
12
- const fakeDecoder: ImageDecoder = async (): Promise<DecodedImage> => ({
13
- data: new Uint8ClampedArray(4),
14
- width: 1,
15
- height: 1,
16
- });
17
-
18
- afterEach(() => {
19
- clearImageDecoders();
20
- });
21
-
22
- describe('clearImageDecoders', () => {
23
- it('removes every registered decoder', () => {
24
- registerImageDecoder('image/png', fakeDecoder);
25
- registerImageDecoder('image/jpeg', fakeDecoder);
26
- clearImageDecoders();
27
- expect(hasImageDecoder('image/png')).toBe(false);
28
- expect(hasImageDecoder('image/jpeg')).toBe(false);
29
- });
30
- });
31
-
32
- describe('getImageDecoder', () => {
33
- it('returns the registered decoder', () => {
34
- registerImageDecoder('image/png', fakeDecoder);
35
- expect(getImageDecoder('image/png')).toBe(fakeDecoder);
36
- });
37
-
38
- it('returns null when no decoder is registered', () => {
39
- expect(getImageDecoder('image/png')).toBeNull();
40
- });
41
- });
42
-
43
- describe('getImageDecoderMimeTypes', () => {
44
- it('returns an empty snapshot before registration', () => {
45
- expect(getImageDecoderMimeTypes()).toEqual([]);
46
- });
47
-
48
- it('returns an insertion-ordered snapshot isolated from the registry', () => {
49
- registerImageDecoder('image/png', fakeDecoder);
50
- registerImageDecoder('image/jpeg', fakeDecoder);
51
- const mimeTypes = getImageDecoderMimeTypes() as string[];
52
- mimeTypes.push('image/webp');
53
- expect(getImageDecoderMimeTypes()).toEqual(['image/png', 'image/jpeg']);
54
- });
55
- });
56
-
57
- describe('hasImageDecoder', () => {
58
- it('reflects registration state', () => {
59
- expect(hasImageDecoder('image/png')).toBe(false);
60
- registerImageDecoder('image/png', fakeDecoder);
61
- expect(hasImageDecoder('image/png')).toBe(true);
62
- });
63
- });
64
-
65
- describe('registerImageDecoder', () => {
66
- it('is empty until called', () => {
67
- expect(hasImageDecoder('image/png')).toBe(false);
68
- });
69
-
70
- it('overwrites an existing decoder (last-write-wins)', () => {
71
- const other: ImageDecoder = async () => ({ data: new Uint8ClampedArray(4), width: 1, height: 1 });
72
- registerImageDecoder('image/png', fakeDecoder);
73
- registerImageDecoder('image/png', other);
74
- expect(getImageDecoder('image/png')).toBe(other);
75
- });
76
- });
77
-
78
- describe('unregisterImageDecoder', () => {
79
- it('removes a single decoder', () => {
80
- registerImageDecoder('image/png', fakeDecoder);
81
- unregisterImageDecoder('image/png');
82
- expect(hasImageDecoder('image/png')).toBe(false);
83
- });
84
- });
@@ -1,80 +0,0 @@
1
- import type { ImageEncoder } from '@flighthq/types/contract';
2
-
3
- import {
4
- clearImageEncoders,
5
- getImageEncoder,
6
- getImageEncoderMimeTypes,
7
- hasImageEncoder,
8
- registerImageEncoder,
9
- unregisterImageEncoder,
10
- } from './imageEncoderRegistry';
11
-
12
- const fakeEncoder: ImageEncoder = async (): Promise<Uint8Array> => new Uint8Array(0);
13
-
14
- afterEach(() => {
15
- clearImageEncoders();
16
- });
17
-
18
- describe('clearImageEncoders', () => {
19
- it('removes every registered encoder', () => {
20
- registerImageEncoder('image/png', fakeEncoder);
21
- registerImageEncoder('image/jpeg', fakeEncoder);
22
- clearImageEncoders();
23
- expect(hasImageEncoder('image/png')).toBe(false);
24
- expect(hasImageEncoder('image/jpeg')).toBe(false);
25
- });
26
- });
27
-
28
- describe('getImageEncoder', () => {
29
- it('returns the registered encoder', () => {
30
- registerImageEncoder('image/png', fakeEncoder);
31
- expect(getImageEncoder('image/png')).toBe(fakeEncoder);
32
- });
33
-
34
- it('returns null when no encoder is registered', () => {
35
- expect(getImageEncoder('image/png')).toBeNull();
36
- });
37
- });
38
-
39
- describe('getImageEncoderMimeTypes', () => {
40
- it('returns an empty snapshot before registration', () => {
41
- expect(getImageEncoderMimeTypes()).toEqual([]);
42
- });
43
-
44
- it('returns an insertion-ordered snapshot isolated from the registry', () => {
45
- registerImageEncoder('image/png', fakeEncoder);
46
- registerImageEncoder('image/jpeg', fakeEncoder);
47
- const mimeTypes = getImageEncoderMimeTypes() as string[];
48
- mimeTypes.push('image/webp');
49
- expect(getImageEncoderMimeTypes()).toEqual(['image/png', 'image/jpeg']);
50
- });
51
- });
52
-
53
- describe('hasImageEncoder', () => {
54
- it('reflects registration state', () => {
55
- expect(hasImageEncoder('image/png')).toBe(false);
56
- registerImageEncoder('image/png', fakeEncoder);
57
- expect(hasImageEncoder('image/png')).toBe(true);
58
- });
59
- });
60
-
61
- describe('registerImageEncoder', () => {
62
- it('is empty until called', () => {
63
- expect(hasImageEncoder('image/png')).toBe(false);
64
- });
65
-
66
- it('overwrites an existing encoder (last-write-wins)', () => {
67
- const other: ImageEncoder = async () => new Uint8Array(1);
68
- registerImageEncoder('image/png', fakeEncoder);
69
- registerImageEncoder('image/png', other);
70
- expect(getImageEncoder('image/png')).toBe(other);
71
- });
72
- });
73
-
74
- describe('unregisterImageEncoder', () => {
75
- it('removes a single encoder', () => {
76
- registerImageEncoder('image/png', fakeEncoder);
77
- unregisterImageEncoder('image/png');
78
- expect(hasImageEncoder('image/png')).toBe(false);
79
- });
80
- });