@meonode/canvas 2.0.4 → 3.0.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.
- package/CONTRIBUTING.md +9 -9
- package/README.md +9 -21
- package/dist/cjs/canvas/canvas.helper.d.ts +1 -1
- package/dist/cjs/canvas/canvas.type.d.ts +9 -4
- package/dist/cjs/canvas/canvas.type.d.ts.map +1 -1
- package/dist/cjs/canvas/chart.canvas.d.ts +7 -3
- package/dist/cjs/canvas/chart.canvas.d.ts.map +1 -1
- package/dist/cjs/canvas/chart.canvas.js +3 -4
- package/dist/cjs/canvas/chart.canvas.js.map +1 -1
- package/dist/cjs/canvas/grid.canvas.d.ts +2 -2
- package/dist/cjs/canvas/grid.canvas.d.ts.map +1 -1
- package/dist/cjs/canvas/grid.canvas.js +2 -8
- package/dist/cjs/canvas/grid.canvas.js.map +1 -1
- package/dist/cjs/canvas/image.canvas.d.ts +2 -2
- package/dist/cjs/canvas/image.canvas.js.map +1 -1
- package/dist/cjs/canvas/layout.canvas.d.ts +5 -1
- package/dist/cjs/canvas/layout.canvas.d.ts.map +1 -1
- package/dist/cjs/canvas/layout.canvas.js +59 -68
- package/dist/cjs/canvas/layout.canvas.js.map +1 -1
- package/dist/cjs/canvas/root.canvas.d.ts +9 -16
- package/dist/cjs/canvas/root.canvas.d.ts.map +1 -1
- package/dist/cjs/canvas/root.canvas.js +56 -43
- package/dist/cjs/canvas/root.canvas.js.map +1 -1
- package/dist/cjs/canvas/text.canvas.d.ts +7 -3
- package/dist/cjs/canvas/text.canvas.d.ts.map +1 -1
- package/dist/cjs/canvas/text.canvas.js +25 -85
- package/dist/cjs/canvas/text.canvas.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/util/disk.cache.d.ts +5 -0
- package/dist/cjs/util/disk.cache.d.ts.map +1 -1
- package/dist/cjs/util/disk.cache.js +23 -8
- package/dist/cjs/util/disk.cache.js.map +1 -1
- package/dist/cjs/worker/comlink.pool.d.ts +15 -4
- package/dist/cjs/worker/comlink.pool.d.ts.map +1 -1
- package/dist/cjs/worker/comlink.pool.js +69 -18
- package/dist/cjs/worker/comlink.pool.js.map +1 -1
- package/dist/cjs/worker/comlink.setup.d.ts.map +1 -1
- package/dist/cjs/worker/comlink.setup.js +1 -2
- package/dist/cjs/worker/comlink.setup.js.map +1 -1
- package/dist/cjs/worker/render.worker.js +4 -2
- package/dist/cjs/worker/render.worker.js.map +1 -1
- package/dist/cjs/worker/worker.types.d.ts +2 -1
- package/dist/cjs/worker/worker.types.d.ts.map +1 -1
- package/dist/esm/canvas/canvas.helper.d.ts +1 -1
- package/dist/esm/canvas/canvas.type.d.ts +9 -4
- package/dist/esm/canvas/canvas.type.d.ts.map +1 -1
- package/dist/esm/canvas/chart.canvas.d.ts +7 -3
- package/dist/esm/canvas/chart.canvas.d.ts.map +1 -1
- package/dist/esm/canvas/chart.canvas.js +3 -4
- package/dist/esm/canvas/grid.canvas.d.ts +2 -2
- package/dist/esm/canvas/grid.canvas.d.ts.map +1 -1
- package/dist/esm/canvas/grid.canvas.js +1 -7
- package/dist/esm/canvas/image.canvas.d.ts +2 -2
- package/dist/esm/canvas/layout.canvas.d.ts +5 -1
- package/dist/esm/canvas/layout.canvas.d.ts.map +1 -1
- package/dist/esm/canvas/layout.canvas.js +59 -69
- package/dist/esm/canvas/root.canvas.d.ts +9 -16
- package/dist/esm/canvas/root.canvas.d.ts.map +1 -1
- package/dist/esm/canvas/root.canvas.js +57 -43
- package/dist/esm/canvas/text.canvas.d.ts +7 -3
- package/dist/esm/canvas/text.canvas.d.ts.map +1 -1
- package/dist/esm/canvas/text.canvas.js +25 -85
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/util/disk.cache.d.ts +5 -0
- package/dist/esm/util/disk.cache.d.ts.map +1 -1
- package/dist/esm/util/disk.cache.js +23 -9
- package/dist/esm/worker/comlink.pool.d.ts +15 -4
- package/dist/esm/worker/comlink.pool.d.ts.map +1 -1
- package/dist/esm/worker/comlink.pool.js +67 -18
- package/dist/esm/worker/comlink.setup.d.ts.map +1 -1
- package/dist/esm/worker/comlink.setup.js +1 -1
- package/dist/esm/worker/render.worker.js +4 -2
- package/dist/esm/worker/worker.types.d.ts +2 -1
- package/dist/esm/worker/worker.types.d.ts.map +1 -1
- package/package.json +9 -16
|
@@ -2,12 +2,20 @@ import { createHash } from 'crypto';
|
|
|
2
2
|
import { promises } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
let _cacheDir = join(process.cwd(), '.cache', 'files');
|
|
6
6
|
let _dirEnsured = false;
|
|
7
|
+
/**
|
|
8
|
+
* Override the default disk cache directory.
|
|
9
|
+
* Must be called before any cache read/write operations.
|
|
10
|
+
*/
|
|
11
|
+
function setDiskCacheDir(dir) {
|
|
12
|
+
_cacheDir = dir;
|
|
13
|
+
_dirEnsured = false;
|
|
14
|
+
}
|
|
7
15
|
async function ensureDir() {
|
|
8
16
|
if (_dirEnsured)
|
|
9
17
|
return;
|
|
10
|
-
await promises.mkdir(
|
|
18
|
+
await promises.mkdir(_cacheDir, { recursive: true });
|
|
11
19
|
_dirEnsured = true;
|
|
12
20
|
}
|
|
13
21
|
function hashBuffer(buf) {
|
|
@@ -16,7 +24,7 @@ function hashBuffer(buf) {
|
|
|
16
24
|
async function readDiskCache(key) {
|
|
17
25
|
try {
|
|
18
26
|
await ensureDir();
|
|
19
|
-
return await promises.readFile(join(
|
|
27
|
+
return await promises.readFile(join(_cacheDir, key));
|
|
20
28
|
}
|
|
21
29
|
catch {
|
|
22
30
|
return null;
|
|
@@ -25,7 +33,7 @@ async function readDiskCache(key) {
|
|
|
25
33
|
async function writeDiskCache(key, data) {
|
|
26
34
|
try {
|
|
27
35
|
await ensureDir();
|
|
28
|
-
await promises.writeFile(join(
|
|
36
|
+
await promises.writeFile(join(_cacheDir, key), data);
|
|
29
37
|
}
|
|
30
38
|
catch {
|
|
31
39
|
// best-effort — cache write failures are non-fatal
|
|
@@ -33,10 +41,13 @@ async function writeDiskCache(key, data) {
|
|
|
33
41
|
}
|
|
34
42
|
async function deleteDiskCache(key) {
|
|
35
43
|
try {
|
|
36
|
-
await promises.unlink(join(
|
|
44
|
+
await promises.unlink(join(_cacheDir, key));
|
|
37
45
|
}
|
|
38
|
-
catch {
|
|
46
|
+
catch (err) {
|
|
39
47
|
// non-fatal — file may not exist if write failed earlier
|
|
48
|
+
if (err.code !== 'ENOENT') {
|
|
49
|
+
console.warn(`[disk.cache] Failed to delete cache entry "${key}":`, err.message);
|
|
50
|
+
}
|
|
40
51
|
}
|
|
41
52
|
}
|
|
42
53
|
/**
|
|
@@ -46,10 +57,13 @@ async function deleteDiskCache(key) {
|
|
|
46
57
|
async function clearDiskCache() {
|
|
47
58
|
_dirEnsured = false;
|
|
48
59
|
try {
|
|
49
|
-
await promises.rm(
|
|
60
|
+
await promises.rm(_cacheDir, { recursive: true, force: true });
|
|
50
61
|
}
|
|
51
|
-
catch {
|
|
62
|
+
catch (err) {
|
|
52
63
|
// non-fatal — directory may not exist
|
|
64
|
+
if (err.code !== 'ENOENT') {
|
|
65
|
+
console.warn('[disk.cache] Failed to clear cache directory:', err.message);
|
|
66
|
+
}
|
|
53
67
|
}
|
|
54
68
|
}
|
|
55
69
|
// Clean up disk cache on process exit to handle crashes mid-render.
|
|
@@ -69,4 +83,4 @@ const cleanupOnExit = () => {
|
|
|
69
83
|
process.on('SIGINT', cleanupOnExit);
|
|
70
84
|
process.on('SIGTERM', cleanupOnExit);
|
|
71
85
|
|
|
72
|
-
export { clearDiskCache, deleteDiskCache, hashBuffer, readDiskCache, writeDiskCache };
|
|
86
|
+
export { clearDiskCache, deleteDiskCache, hashBuffer, readDiskCache, setDiskCacheDir, writeDiskCache };
|
|
@@ -1,13 +1,24 @@
|
|
|
1
|
-
import type { RenderResult } from '
|
|
1
|
+
import type { RenderResult } from './worker.types.js';
|
|
2
2
|
import type { RootProps } from '../canvas/canvas.type.js';
|
|
3
3
|
export interface PoolRenderResult extends RenderResult {
|
|
4
4
|
workerIdx: number;
|
|
5
5
|
}
|
|
6
|
+
/** Sentinel embedded in serialized props to mark where a function was extracted. */
|
|
7
|
+
export declare const FN_MARKER = "__comlinkFnId";
|
|
6
8
|
/**
|
|
7
|
-
* Deeply walks an object tree,
|
|
8
|
-
* and
|
|
9
|
+
* Deeply walks an object tree, replaces function values with `{ [FN_MARKER]: id }` sentinels,
|
|
10
|
+
* and collects the original functions in a Map keyed by their assigned id.
|
|
11
|
+
* Returns the cleaned (function-free) tree that is safe for structured clone.
|
|
9
12
|
*/
|
|
10
|
-
export declare function
|
|
13
|
+
export declare function extractFunctions<T>(obj: T, fnMap: Map<number, (...args: unknown[]) => unknown>, nextId: {
|
|
14
|
+
value: number;
|
|
15
|
+
}): T;
|
|
16
|
+
/**
|
|
17
|
+
* Deeply walks an object tree received on the worker side, replaces
|
|
18
|
+
* `{ [FN_MARKER]: id }` sentinels with async functions that delegate
|
|
19
|
+
* to the main-thread callback proxy.
|
|
20
|
+
*/
|
|
21
|
+
export declare function restoreFunctions<T>(obj: T, callFn: (id: number, ...args: unknown[]) => Promise<unknown>): T;
|
|
11
22
|
/**
|
|
12
23
|
* Pool of Comlink-wrapped worker threads.
|
|
13
24
|
* Manages idle/queue scheduling and proxy lifecycle.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comlink.pool.d.ts","sourceRoot":"","sources":["../../../src/worker/comlink.pool.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAa,YAAY,
|
|
1
|
+
{"version":3,"file":"comlink.pool.d.ts","sourceRoot":"","sources":["../../../src/worker/comlink.pool.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAa,YAAY,EAAU,MAAM,0BAA0B,CAAA;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,SAAS,EAAE,MAAM,CAAA;CAClB;AASD,oFAAoF;AACpF,eAAO,MAAM,SAAS,kBAAkB,CAAA;AAExC;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,EAAE,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,CAAC,CAuB7H;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAuB3G;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,KAAK,CAAmB;gBAEpB,IAAI,EAAE,MAAM;IAYxB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,KAAK;YAQC,aAAa;IAiBrB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA2DzD,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAInH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIxD,SAAS;CAOV"}
|
|
@@ -5,17 +5,20 @@ import './comlink.setup.js';
|
|
|
5
5
|
import * as Comlink from 'comlink';
|
|
6
6
|
import nodeEndpoint from 'comlink/dist/esm/node-adapter.mjs';
|
|
7
7
|
|
|
8
|
+
/** Sentinel embedded in serialized props to mark where a function was extracted. */
|
|
9
|
+
const FN_MARKER = '__comlinkFnId';
|
|
8
10
|
/**
|
|
9
|
-
* Deeply walks an object tree,
|
|
10
|
-
* and
|
|
11
|
+
* Deeply walks an object tree, replaces function values with `{ [FN_MARKER]: id }` sentinels,
|
|
12
|
+
* and collects the original functions in a Map keyed by their assigned id.
|
|
13
|
+
* Returns the cleaned (function-free) tree that is safe for structured clone.
|
|
11
14
|
*/
|
|
12
|
-
function
|
|
15
|
+
function extractFunctions(obj, fnMap, nextId) {
|
|
13
16
|
if (obj === null || obj === undefined)
|
|
14
17
|
return obj;
|
|
15
18
|
if (typeof obj === 'function') {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
return
|
|
19
|
+
const id = nextId.value++;
|
|
20
|
+
fnMap.set(id, obj);
|
|
21
|
+
return { [FN_MARKER]: id };
|
|
19
22
|
}
|
|
20
23
|
if (typeof obj !== 'object')
|
|
21
24
|
return obj;
|
|
@@ -27,11 +30,41 @@ function wrapFunctions(obj, proxies) {
|
|
|
27
30
|
if (ArrayBuffer.isView(obj))
|
|
28
31
|
return obj;
|
|
29
32
|
if (Array.isArray(obj)) {
|
|
30
|
-
return obj.map(item =>
|
|
33
|
+
return obj.map(item => extractFunctions(item, fnMap, nextId));
|
|
31
34
|
}
|
|
32
35
|
const result = {};
|
|
33
36
|
for (const key of Object.keys(obj)) {
|
|
34
|
-
result[key] =
|
|
37
|
+
result[key] = extractFunctions(obj[key], fnMap, nextId);
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Deeply walks an object tree received on the worker side, replaces
|
|
43
|
+
* `{ [FN_MARKER]: id }` sentinels with async functions that delegate
|
|
44
|
+
* to the main-thread callback proxy.
|
|
45
|
+
*/
|
|
46
|
+
function restoreFunctions(obj, callFn) {
|
|
47
|
+
if (obj === null || obj === undefined)
|
|
48
|
+
return obj;
|
|
49
|
+
if (typeof obj !== 'object')
|
|
50
|
+
return obj;
|
|
51
|
+
if (Buffer.isBuffer(obj))
|
|
52
|
+
return obj;
|
|
53
|
+
if (obj instanceof ArrayBuffer)
|
|
54
|
+
return obj;
|
|
55
|
+
if (ArrayBuffer.isView(obj))
|
|
56
|
+
return obj;
|
|
57
|
+
// Check for sentinel
|
|
58
|
+
if (FN_MARKER in obj) {
|
|
59
|
+
const id = obj[FN_MARKER];
|
|
60
|
+
return ((...args) => callFn(id, ...args));
|
|
61
|
+
}
|
|
62
|
+
if (Array.isArray(obj)) {
|
|
63
|
+
return obj.map(item => restoreFunctions(item, callFn));
|
|
64
|
+
}
|
|
65
|
+
const result = {};
|
|
66
|
+
for (const key of Object.keys(obj)) {
|
|
67
|
+
result[key] = restoreFunctions(obj[key], callFn);
|
|
35
68
|
}
|
|
36
69
|
return result;
|
|
37
70
|
}
|
|
@@ -65,12 +98,12 @@ class ComlinkPool {
|
|
|
65
98
|
while (this.queue.length > 0 && this.idle.length > 0) {
|
|
66
99
|
const task = this.queue.shift();
|
|
67
100
|
const idx = this.idle.pop();
|
|
68
|
-
void this.executeRender(idx, task.props, task.resolve, task.reject);
|
|
101
|
+
void this.executeRender(idx, task.props, task.callFn, task.resolve, task.reject);
|
|
69
102
|
}
|
|
70
103
|
}
|
|
71
|
-
async executeRender(idx, props, resolve, reject) {
|
|
104
|
+
async executeRender(idx, props, callFn, resolve, reject) {
|
|
72
105
|
try {
|
|
73
|
-
const result = await this.endpoints[idx].render(props);
|
|
106
|
+
const result = await this.endpoints[idx].render(props, callFn);
|
|
74
107
|
resolve({ ...result, workerIdx: idx });
|
|
75
108
|
}
|
|
76
109
|
catch (err) {
|
|
@@ -81,13 +114,28 @@ class ComlinkPool {
|
|
|
81
114
|
}
|
|
82
115
|
}
|
|
83
116
|
async render(props) {
|
|
84
|
-
|
|
85
|
-
|
|
117
|
+
if (this.endpoints.length === 0) {
|
|
118
|
+
throw new Error('[ComlinkPool] Pool has been terminated');
|
|
119
|
+
}
|
|
120
|
+
// Extract functions from props, replacing them with serializable sentinels.
|
|
121
|
+
// A single Comlink.proxy() callback is created at the top level so Comlink
|
|
122
|
+
// can correctly transfer it via its proxy transfer handler.
|
|
123
|
+
const fnMap = new Map();
|
|
124
|
+
const cleaned = extractFunctions(props, fnMap, { value: 0 });
|
|
125
|
+
let callFnProxy;
|
|
126
|
+
if (fnMap.size > 0) {
|
|
127
|
+
callFnProxy = Comlink.proxy(async (id, ...args) => {
|
|
128
|
+
const fn = fnMap.get(id);
|
|
129
|
+
if (!fn)
|
|
130
|
+
throw new Error(`[ComlinkPool] Function #${id} not found`);
|
|
131
|
+
return fn(...args);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
86
134
|
const cleanup = () => {
|
|
87
|
-
|
|
135
|
+
if (callFnProxy) {
|
|
88
136
|
try {
|
|
89
137
|
;
|
|
90
|
-
|
|
138
|
+
callFnProxy[Comlink.releaseProxy]?.();
|
|
91
139
|
}
|
|
92
140
|
catch {
|
|
93
141
|
// Proxy may already be released
|
|
@@ -98,7 +146,7 @@ class ComlinkPool {
|
|
|
98
146
|
const idx = this.acquire();
|
|
99
147
|
if (idx !== null) {
|
|
100
148
|
try {
|
|
101
|
-
const result = await this.endpoints[idx].render(
|
|
149
|
+
const result = await this.endpoints[idx].render(cleaned, callFnProxy);
|
|
102
150
|
return { ...result, workerIdx: idx };
|
|
103
151
|
}
|
|
104
152
|
finally {
|
|
@@ -109,7 +157,8 @@ class ComlinkPool {
|
|
|
109
157
|
// Queued path — cleanup AFTER the queued task completes, not before
|
|
110
158
|
return new Promise((resolve, reject) => {
|
|
111
159
|
this.queue.push({
|
|
112
|
-
props:
|
|
160
|
+
props: cleaned,
|
|
161
|
+
callFn: callFnProxy,
|
|
113
162
|
resolve: result => {
|
|
114
163
|
cleanup();
|
|
115
164
|
resolve(result);
|
|
@@ -136,4 +185,4 @@ class ComlinkPool {
|
|
|
136
185
|
}
|
|
137
186
|
}
|
|
138
187
|
|
|
139
|
-
export { ComlinkPool,
|
|
188
|
+
export { ComlinkPool, FN_MARKER, extractFunctions, restoreFunctions };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comlink.setup.d.ts","sourceRoot":"","sources":["../../../src/worker/comlink.setup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAA;AAKlC,OAAO,YAAY,MAAM,mCAAmC,CAAA;
|
|
1
|
+
{"version":3,"file":"comlink.setup.d.ts","sourceRoot":"","sources":["../../../src/worker/comlink.setup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAA;AAKlC,OAAO,YAAY,MAAM,mCAAmC,CAAA;AA4B5D,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,CAAA"}
|
|
@@ -14,7 +14,7 @@ export { default as nodeEndpoint } from 'comlink/dist/esm/node-adapter.mjs';
|
|
|
14
14
|
*/
|
|
15
15
|
function installNodeProxyHandler() {
|
|
16
16
|
Comlink.transferHandlers.set('proxy', {
|
|
17
|
-
canHandle: (obj) => typeof obj === 'object' && obj !== null && Comlink.proxyMarker in obj,
|
|
17
|
+
canHandle: (obj) => (typeof obj === 'object' || typeof obj === 'function') && obj !== null && Comlink.proxyMarker in obj,
|
|
18
18
|
serialize: (obj) => {
|
|
19
19
|
const { port1, port2 } = new MessageChannel();
|
|
20
20
|
Comlink.expose(obj, nodeEndpoint(port1));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parentPort } from 'node:worker_threads';
|
|
2
2
|
import './comlink.setup.js';
|
|
3
|
+
import { restoreFunctions } from './comlink.pool.js';
|
|
3
4
|
import { RootNode } from '../canvas/root.canvas.js';
|
|
4
5
|
import * as Comlink from 'comlink';
|
|
5
6
|
import nodeEndpoint from 'comlink/dist/esm/node-adapter.mjs';
|
|
@@ -10,8 +11,9 @@ if (!parentPort) {
|
|
|
10
11
|
const canvases = new Map();
|
|
11
12
|
let nextCanvasId = 0;
|
|
12
13
|
const api = {
|
|
13
|
-
async render(props) {
|
|
14
|
-
const
|
|
14
|
+
async render(props, callFn) {
|
|
15
|
+
const resolved = callFn ? restoreFunctions(props, callFn) : props;
|
|
16
|
+
const canvas = await new RootNode(resolved).render();
|
|
15
17
|
const canvasId = nextCanvasId++;
|
|
16
18
|
canvases.set(canvasId, canvas);
|
|
17
19
|
const result = {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RootProps } from '../canvas/canvas.type.js';
|
|
2
|
+
export type CallFn = (id: number, ...args: unknown[]) => Promise<unknown>;
|
|
2
3
|
export interface RenderResult {
|
|
3
4
|
canvasId: number;
|
|
4
5
|
buffer: Buffer;
|
|
@@ -6,7 +7,7 @@ export interface RenderResult {
|
|
|
6
7
|
height: number;
|
|
7
8
|
}
|
|
8
9
|
export interface WorkerAPI {
|
|
9
|
-
render(props: RootProps): Promise<RenderResult>;
|
|
10
|
+
render(props: RootProps, callFn?: CallFn): Promise<RenderResult>;
|
|
10
11
|
callOnCanvas(canvasId: number, method: string, args: unknown[]): Promise<Buffer | string | void>;
|
|
11
12
|
releaseCanvas(canvasId: number): void;
|
|
12
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.types.d.ts","sourceRoot":"","sources":["../../../src/worker/worker.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"worker.types.d.ts","sourceRoot":"","sources":["../../../src/worker/worker.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,MAAM,MAAM,MAAM,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAEzE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAChE,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,CAAA;IAChG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACtC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meonode/canvas",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "A declarative, component-based library for server-side canvas image generation. Write complex visuals with simple functions, similar to the composition style of @meonode/ui.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"canvas",
|
|
@@ -37,9 +37,10 @@
|
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
|
-
"build": "
|
|
41
|
-
"test": "
|
|
42
|
-
"
|
|
40
|
+
"build": "bun -e \"fs.rmSync('./dist', {recursive:true, force:true})\" && rollup -c --bundleConfigAsCjs && bun scripts/rewrite-dts-aliases.ts",
|
|
41
|
+
"test": "vitest run --coverage",
|
|
42
|
+
"typecheck": "tsc --noEmit",
|
|
43
|
+
"lint": "eslint . --ext .ts,.tsx,.js,.jsx,.mjs --fix && bun run typecheck",
|
|
43
44
|
"format": "prettier --write .",
|
|
44
45
|
"generate:samples": "npx tsx scripts/generate_sample_charts.ts && npx tsx scripts/generate_sample_grids.ts && npx tsx scripts/generate_sample_nested_grids.ts",
|
|
45
46
|
"check:memory": "npx tsx --expose-gc scripts/check_memory.ts",
|
|
@@ -47,7 +48,6 @@
|
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"@eslint/js": "^9.39.4",
|
|
50
|
-
"@jest/globals": "^30.3.0",
|
|
51
51
|
"@rollup/plugin-commonjs": "^29.0.2",
|
|
52
52
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
53
53
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
@@ -56,37 +56,30 @@
|
|
|
56
56
|
"@semantic-release/gitlab": "^13.3.2",
|
|
57
57
|
"@semantic-release/npm": "^13.1.5",
|
|
58
58
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
59
|
-
"@types/jest": "^30.0.0",
|
|
60
|
-
"@types/lodash-es": "^4.17.12",
|
|
61
59
|
"@types/node": "^25.5.0",
|
|
62
60
|
"@types/sharp": "^0.32.0",
|
|
63
|
-
"@types/tinycolor2": "^1.4.6",
|
|
64
61
|
"@typescript-eslint/eslint-plugin": "^8.57.2",
|
|
65
62
|
"@typescript-eslint/parser": "^8.57.2",
|
|
63
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
66
64
|
"eslint": "^9.39.4",
|
|
67
65
|
"eslint-config-prettier": "^10.1.8",
|
|
68
66
|
"eslint-plugin-jsdoc": "^62.8.1",
|
|
69
67
|
"eslint-plugin-prettier": "^5.5.5",
|
|
70
68
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
71
69
|
"husky": "^9.1.7",
|
|
72
|
-
"jest": "^30.3.0",
|
|
73
70
|
"prettier": "^3.8.1",
|
|
74
71
|
"rollup": "^4.60.0",
|
|
75
72
|
"rollup-plugin-tsconfig-paths": "^1.5.2",
|
|
76
|
-
"semantic-release": "
|
|
77
|
-
"ts-jest": "^29.4.6",
|
|
78
|
-
"tsc-alias": "^1.8.16",
|
|
73
|
+
"semantic-release": "24.2.9",
|
|
79
74
|
"typescript": "^6.0.2",
|
|
80
|
-
"typescript-eslint": "^8.57.2"
|
|
75
|
+
"typescript-eslint": "^8.57.2",
|
|
76
|
+
"vitest": "^3.2.4"
|
|
81
77
|
},
|
|
82
|
-
"packageManager": "yarn@4.11.0",
|
|
83
78
|
"dependencies": {
|
|
84
79
|
"comlink": "^4.4.2",
|
|
85
80
|
"file-type": "^22.0.0",
|
|
86
|
-
"lodash-es": "^4.17.23",
|
|
87
81
|
"sharp": "^0.34.5",
|
|
88
82
|
"skia-canvas": "^3.0.8",
|
|
89
|
-
"tinycolor2": "^1.6.0",
|
|
90
83
|
"tslib": "^2.8.1",
|
|
91
84
|
"yoga-layout": "^3.2.1"
|
|
92
85
|
},
|