@takumi-rs/image-response 0.29.2 → 0.29.4
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/dist/index.cjs +1 -0
- package/dist/index.d.cts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +1 -0
- package/package.json +7 -1
- package/src/index.ts +0 -74
- package/tests/image-response.test.tsx +0 -13
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var r=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var y=(n,e)=>{for(var t in e)r(n,t,{get:e[t],enumerable:!0})},R=(n,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of u(e))!l.call(n,s)&&s!==t&&r(n,s,{get:()=>e[s],enumerable:!(a=m(e,s))||a.enumerable});return n};var g=n=>R(r({},"__esModule",{value:!0}),n);var x={};y(x,{default:()=>o,loadFonts:()=>f});module.exports=g(x);var d=require("@takumi-rs/core"),i=require("@takumi-rs/helpers/jsx"),p=new d.Renderer,c=new WeakSet,h={width:1200,height:630,format:"webp"};function f(n){let e=n.filter(t=>!c.has(t));for(let t of e)c.add(t);return p.loadFontsAsync(e)}function w(n,e){return new ReadableStream({async start(t){try{e?.fonts&&await f(e.fonts);let a=await(0,i.fromJsx)(n),s=await p.renderAsync(a,e??h,e?.signal);t.enqueue(s),t.close()}catch(a){t.error(a)}}})}var o=class extends Response{constructor(e,t){let a=w(e,t),s=new Headers(t?.headers);s.set("Content-Type","image/webp"),s.get("cache-control")||s.set("cache-control","public, max-age=0, must-revalidate"),super(a,{status:t?.status,statusText:t?.statusText,headers:s})}};0&&(module.exports={loadFonts});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RenderOptions, Renderer } from '@takumi-rs/core';
|
|
2
|
+
import { HeadersInit } from 'bun';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
declare const renderer: Renderer;
|
|
6
|
+
type Font = Parameters<typeof renderer.loadFontAsync>[0];
|
|
7
|
+
type ImageResponseOptions = RenderOptions & ResponseInit & {
|
|
8
|
+
headers?: HeadersInit;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
fonts?: Font[];
|
|
11
|
+
};
|
|
12
|
+
declare function loadFonts(fonts: Font[]): Promise<number>;
|
|
13
|
+
declare class ImageResponse extends Response {
|
|
14
|
+
constructor(component: ReactNode, options?: ImageResponseOptions);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { type Font, type ImageResponseOptions, ImageResponse as default, loadFonts };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RenderOptions, Renderer } from '@takumi-rs/core';
|
|
2
|
+
import { HeadersInit } from 'bun';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
declare const renderer: Renderer;
|
|
6
|
+
type Font = Parameters<typeof renderer.loadFontAsync>[0];
|
|
7
|
+
type ImageResponseOptions = RenderOptions & ResponseInit & {
|
|
8
|
+
headers?: HeadersInit;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
fonts?: Font[];
|
|
11
|
+
};
|
|
12
|
+
declare function loadFonts(fonts: Font[]): Promise<number>;
|
|
13
|
+
declare class ImageResponse extends Response {
|
|
14
|
+
constructor(component: ReactNode, options?: ImageResponseOptions);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { type Font, type ImageResponseOptions, ImageResponse as default, loadFonts };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Renderer as d}from"@takumi-rs/core";import{fromJsx as i}from"@takumi-rs/helpers/jsx";var c=new d,r=new WeakSet,p={width:1200,height:630,format:"webp"};function f(a){let t=a.filter(e=>!r.has(e));for(let e of t)r.add(e);return c.loadFontsAsync(t)}function m(a,t){return new ReadableStream({async start(e){try{t?.fonts&&await f(t.fonts);let s=await i(a),n=await c.renderAsync(s,t??p,t?.signal);e.enqueue(n),e.close()}catch(s){e.error(s)}}})}var o=class extends Response{constructor(t,e){let s=m(t,e),n=new Headers(e?.headers);n.set("Content-Type","image/webp"),n.get("cache-control")||n.set("cache-control","public, max-age=0, must-revalidate"),super(s,{status:e?.status,statusText:e?.statusText,headers:n})}};export{o as default,f as loadFonts};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@takumi-rs/image-response",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.29.
|
|
4
|
+
"version": "0.29.4",
|
|
5
5
|
"author": {
|
|
6
6
|
"email": "me@kane.tw",
|
|
7
7
|
"name": "Kane Wang",
|
|
@@ -26,6 +26,12 @@
|
|
|
26
26
|
"scripts": {
|
|
27
27
|
"build": "tsup-node src/index.ts --minify --dts --format esm,cjs --no-splitting"
|
|
28
28
|
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"package.json",
|
|
32
|
+
"README.md",
|
|
33
|
+
"tsconfig.json"
|
|
34
|
+
],
|
|
29
35
|
"exports": {
|
|
30
36
|
".": {
|
|
31
37
|
"types": "./dist/index.d.ts",
|
package/src/index.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { Renderer, type RenderOptions } from "@takumi-rs/core";
|
|
2
|
-
import { fromJsx } from "@takumi-rs/helpers/jsx";
|
|
3
|
-
import type { HeadersInit } from "bun";
|
|
4
|
-
import type { ReactNode } from "react";
|
|
5
|
-
|
|
6
|
-
const renderer = new Renderer();
|
|
7
|
-
|
|
8
|
-
const fontLoadMarker = new WeakSet<Font>();
|
|
9
|
-
|
|
10
|
-
export type Font = Parameters<typeof renderer.loadFontAsync>[0];
|
|
11
|
-
|
|
12
|
-
export type ImageResponseOptions = RenderOptions &
|
|
13
|
-
ResponseInit & {
|
|
14
|
-
headers?: HeadersInit;
|
|
15
|
-
signal?: AbortSignal;
|
|
16
|
-
fonts?: Font[];
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const defaultOptions: ImageResponseOptions = {
|
|
20
|
-
width: 1200,
|
|
21
|
-
height: 630,
|
|
22
|
-
format: "webp",
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export function loadFonts(fonts: Font[]) {
|
|
26
|
-
const fontsToLoad = fonts.filter((font) => !fontLoadMarker.has(font));
|
|
27
|
-
|
|
28
|
-
for (const font of fontsToLoad) {
|
|
29
|
-
fontLoadMarker.add(font);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return renderer.loadFontsAsync(fontsToLoad);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function createStream(component: ReactNode, options?: ImageResponseOptions) {
|
|
36
|
-
return new ReadableStream({
|
|
37
|
-
async start(controller) {
|
|
38
|
-
try {
|
|
39
|
-
if (options?.fonts) await loadFonts(options.fonts);
|
|
40
|
-
|
|
41
|
-
const node = await fromJsx(component);
|
|
42
|
-
const image = await renderer.renderAsync(
|
|
43
|
-
node,
|
|
44
|
-
options ?? defaultOptions,
|
|
45
|
-
options?.signal,
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
controller.enqueue(image);
|
|
49
|
-
controller.close();
|
|
50
|
-
} catch (error) {
|
|
51
|
-
controller.error(error);
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export default class ImageResponse extends Response {
|
|
58
|
-
constructor(component: ReactNode, options?: ImageResponseOptions) {
|
|
59
|
-
const stream = createStream(component, options);
|
|
60
|
-
const headers = new Headers(options?.headers);
|
|
61
|
-
|
|
62
|
-
headers.set("Content-Type", "image/webp");
|
|
63
|
-
|
|
64
|
-
if (!headers.get("cache-control")) {
|
|
65
|
-
headers.set("cache-control", "public, max-age=0, must-revalidate");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
super(stream, {
|
|
69
|
-
status: options?.status,
|
|
70
|
-
statusText: options?.statusText,
|
|
71
|
-
headers,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import ImageResponse from "../src";
|
|
3
|
-
|
|
4
|
-
describe("ImageResponse", () => {
|
|
5
|
-
test("should not crash", async () => {
|
|
6
|
-
const response = new ImageResponse(<div>Hello</div>);
|
|
7
|
-
|
|
8
|
-
expect(response.status).toBe(200);
|
|
9
|
-
expect(response.headers.get("content-type")).toBe("image/webp");
|
|
10
|
-
|
|
11
|
-
expect(await response.arrayBuffer()).toBeDefined();
|
|
12
|
-
});
|
|
13
|
-
});
|