founders card

This commit is contained in:
2026-09-14 13:23:14 +00:00
parent c5084170b8
commit 64759ce17d
57 changed files with 5013 additions and 188 deletions
+90
View File
@@ -0,0 +1,90 @@
import { createRequire } from "node:module";
import os from "node:os";
import path from "node:path";
import type { DrawStyle } from "@/lib/card-gen/id-config";
export type GenerateTask = {
text: string;
outPath: string;
};
export type WorkerFont = {
path: string;
family: string;
};
type WorkerMsg =
| { type: "progress" }
| { type: "error"; message: string };
export async function generatePngsInWorkers(args: {
imagePath: string;
fonts: WorkerFont[];
style: DrawStyle;
tasks: GenerateTask[];
onProgress: (current: number, total: number) => void;
}): Promise<void> {
const { imagePath, fonts, style, tasks, onProgress } = args;
if (tasks.length === 0) return;
const require = createRequire(path.join(process.cwd(), "package.json"));
const threads = require("node:worker_threads") as typeof import("node:worker_threads");
const workerCount = Math.max(
1,
Math.min(os.cpus().length || 1, 8, tasks.length),
);
const buckets: GenerateTask[][] = Array.from(
{ length: workerCount },
() => [],
);
tasks.forEach((task, i) => {
buckets[i % workerCount]!.push(task);
});
const workerPath = path.join(process.cwd(), "workers", "generate-id.cjs");
let completed = 0;
const total = tasks.length;
await Promise.all(
buckets
.filter((bucket) => bucket.length > 0)
.map(
(bucket) =>
new Promise<void>((resolve, reject) => {
const worker = new threads.Worker(workerPath, {
workerData: {
imagePath,
fonts,
style,
tasks: bucket,
},
});
let settled = false;
const fail = (err: Error) => {
if (settled) return;
settled = true;
void worker.terminate();
reject(err);
};
worker.on("message", (msg: WorkerMsg) => {
if (msg?.type === "progress") {
completed += 1;
onProgress(completed, total);
return;
}
if (msg?.type === "error") {
fail(new Error(msg.message || "Worker error"));
}
});
worker.on("error", (err) => fail(err));
worker.on("exit", (code) => {
if (settled) return;
settled = true;
if (code === 0) resolve();
else reject(new Error(`Worker exited with code ${code}`));
});
}),
),
);
}