@hanzogui/static-worker 2.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/dist/cjs/index.cjs +256 -0
- package/dist/esm/index.js +213 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/index.mjs +213 -0
- package/dist/esm/index.mjs.map +1 -0
- package/package.json +46 -0
- package/src/index.ts +402 -0
- package/types/index.d.ts +70 -0
- package/types/index.d.ts.map +1 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf,
|
|
6
|
+
__hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all) __defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: !0
|
|
11
|
+
});
|
|
12
|
+
},
|
|
13
|
+
__copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from == "object" || typeof from == "function") for (let key of __getOwnPropNames(from)) !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, {
|
|
15
|
+
get: () => from[key],
|
|
16
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
17
|
+
});
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
26
|
+
value: mod,
|
|
27
|
+
enumerable: !0
|
|
28
|
+
}) : target, mod)),
|
|
29
|
+
__toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
30
|
+
value: !0
|
|
31
|
+
}), mod);
|
|
32
|
+
var index_exports = {};
|
|
33
|
+
__export(index_exports, {
|
|
34
|
+
clearWorkerCache: () => clearWorkerCache,
|
|
35
|
+
destroyPool: () => destroyPool,
|
|
36
|
+
extractToClassNames: () => extractToClassNames,
|
|
37
|
+
extractToNative: () => extractToNative,
|
|
38
|
+
getPoolStats: () => getPoolStats,
|
|
39
|
+
getPragmaOptions: () => getPragmaOptions,
|
|
40
|
+
loadGui: () => loadGui,
|
|
41
|
+
loadGuiBuildConfig: () => loadGuiBuildConfig,
|
|
42
|
+
watchGuiConfig: () => watchGuiConfig
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(index_exports);
|
|
45
|
+
var import_node_url = require("node:url"),
|
|
46
|
+
import_piscina = __toESM(require("piscina"), 1);
|
|
47
|
+
const import_meta = {},
|
|
48
|
+
getPragmaOptions = async props => {
|
|
49
|
+
const {
|
|
50
|
+
default: Static
|
|
51
|
+
} = await import("@hanzogui/static");
|
|
52
|
+
return Static.getPragmaOptions(props);
|
|
53
|
+
},
|
|
54
|
+
getWorkerPath = () => typeof import_meta < "u" && import_meta.url ? (0, import_node_url.fileURLToPath)(import_meta.resolve("@hanzogui/static/worker")).replace(/\.mjs$/, ".js") : require.resolve("@hanzogui/static/worker").replace(/\.mjs$/, ".js"),
|
|
55
|
+
POOL_KEY = "__gui_piscina_pool__",
|
|
56
|
+
CLOSING_KEY = "__gui_piscina_closing__",
|
|
57
|
+
TASK_COUNT_KEY = "__gui_piscina_task_count__",
|
|
58
|
+
RECYCLING_KEY = "__gui_piscina_recycling__",
|
|
59
|
+
MAX_TASKS_BEFORE_RECYCLE = 1e3;
|
|
60
|
+
function getSharedPool() {
|
|
61
|
+
return globalThis[POOL_KEY] ?? null;
|
|
62
|
+
}
|
|
63
|
+
function setSharedPool(pool) {
|
|
64
|
+
globalThis[POOL_KEY] = pool;
|
|
65
|
+
}
|
|
66
|
+
function isClosing() {
|
|
67
|
+
return globalThis[CLOSING_KEY] === !0;
|
|
68
|
+
}
|
|
69
|
+
function setClosing(value) {
|
|
70
|
+
globalThis[CLOSING_KEY] = value;
|
|
71
|
+
}
|
|
72
|
+
function isRecycling() {
|
|
73
|
+
return globalThis[RECYCLING_KEY] === !0;
|
|
74
|
+
}
|
|
75
|
+
function setRecycling(value) {
|
|
76
|
+
globalThis[RECYCLING_KEY] = value;
|
|
77
|
+
}
|
|
78
|
+
function getTaskCount() {
|
|
79
|
+
return globalThis[TASK_COUNT_KEY] ?? 0;
|
|
80
|
+
}
|
|
81
|
+
function incrementTaskCount() {
|
|
82
|
+
const count = getTaskCount() + 1;
|
|
83
|
+
return globalThis[TASK_COUNT_KEY] = count, count;
|
|
84
|
+
}
|
|
85
|
+
function resetTaskCount() {
|
|
86
|
+
globalThis[TASK_COUNT_KEY] = 0;
|
|
87
|
+
}
|
|
88
|
+
function createPool() {
|
|
89
|
+
const pool = new import_piscina.default({
|
|
90
|
+
filename: getWorkerPath(),
|
|
91
|
+
// each worker loads and caches config independently
|
|
92
|
+
minThreads: 2,
|
|
93
|
+
maxThreads: 2,
|
|
94
|
+
// Never terminate due to idle - worker stays alive until close() or process exit
|
|
95
|
+
// This prevents "Terminating worker thread" errors from Piscina during idle
|
|
96
|
+
idleTimeout: Number.POSITIVE_INFINITY
|
|
97
|
+
// no resourceLimits - we rely on task-based recycling instead
|
|
98
|
+
// V8 resourceLimits cause "Terminating worker thread" messages when hit
|
|
99
|
+
});
|
|
100
|
+
return pool.on("error", err => {
|
|
101
|
+
isClosing() || isRecycling() || (err && typeof err == "object" && "message" in err ? String(err.message) : "").includes("Terminating worker thread") || console.error("[hanzo-gui] Worker pool error:", err);
|
|
102
|
+
}), pool;
|
|
103
|
+
}
|
|
104
|
+
function getPool() {
|
|
105
|
+
let pool = getSharedPool();
|
|
106
|
+
return pool || (pool = createPool(), setSharedPool(pool)), pool;
|
|
107
|
+
}
|
|
108
|
+
async function loadGui(options) {
|
|
109
|
+
const pool = getPool(),
|
|
110
|
+
task = {
|
|
111
|
+
type: "extractToClassNames",
|
|
112
|
+
source: "// dummy",
|
|
113
|
+
sourcePath: "__dummy__.tsx",
|
|
114
|
+
options: {
|
|
115
|
+
components: ["@hanzo/gui"],
|
|
116
|
+
...options
|
|
117
|
+
},
|
|
118
|
+
shouldPrintDebug: !1
|
|
119
|
+
};
|
|
120
|
+
try {
|
|
121
|
+
return await pool.run(task, {
|
|
122
|
+
name: "runTask"
|
|
123
|
+
}), {
|
|
124
|
+
success: !0
|
|
125
|
+
};
|
|
126
|
+
} catch (error) {
|
|
127
|
+
throw console.error("[static-worker] Error loading Hanzo GUI config:", error), error;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function recyclePool(options) {
|
|
131
|
+
if (isClosing() || isRecycling()) return;
|
|
132
|
+
const oldPool = getSharedPool();
|
|
133
|
+
if (!oldPool) return;
|
|
134
|
+
setRecycling(!0);
|
|
135
|
+
const start = Date.now();
|
|
136
|
+
try {
|
|
137
|
+
const originalStderr = process.stderr.write.bind(process.stderr),
|
|
138
|
+
originalStdout = process.stdout.write.bind(process.stdout),
|
|
139
|
+
filter = (chunk, ...args) => !!(typeof chunk == "string" ? chunk : chunk?.toString?.() || "").includes("Terminating worker thread");
|
|
140
|
+
process.stderr.write = (chunk, ...args) => filter(chunk) ? !0 : originalStderr(chunk, ...args), process.stdout.write = (chunk, ...args) => filter(chunk) ? !0 : originalStdout(chunk, ...args);
|
|
141
|
+
const newPool = createPool();
|
|
142
|
+
setSharedPool(newPool);
|
|
143
|
+
const warmupTask = {
|
|
144
|
+
type: "extractToClassNames",
|
|
145
|
+
source: "// warmup",
|
|
146
|
+
sourcePath: "__warmup__.tsx",
|
|
147
|
+
options: {
|
|
148
|
+
...options,
|
|
149
|
+
// skip the "built config" log on warmup since it's a recycle
|
|
150
|
+
_skipBuildLog: !0
|
|
151
|
+
},
|
|
152
|
+
shouldPrintDebug: !1
|
|
153
|
+
};
|
|
154
|
+
await newPool.run(warmupTask, {
|
|
155
|
+
name: "runTask"
|
|
156
|
+
}), oldPool.removeAllListeners(), oldPool.destroy().catch(() => {}), setTimeout(() => {
|
|
157
|
+
process.stderr.write = originalStderr, process.stdout.write = originalStdout;
|
|
158
|
+
}), console.log(` \u267B\uFE0F [hanzo-gui] recycled worker pool (${Date.now() - start}ms)`);
|
|
159
|
+
} finally {
|
|
160
|
+
setRecycling(!1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async function loadGuiBuildConfig(guiOptions) {
|
|
164
|
+
const {
|
|
165
|
+
default: Static
|
|
166
|
+
} = await import("@hanzogui/static");
|
|
167
|
+
return Static.loadGuiBuildConfigAsync(guiOptions);
|
|
168
|
+
}
|
|
169
|
+
async function extractToClassNames(params) {
|
|
170
|
+
const {
|
|
171
|
+
source,
|
|
172
|
+
sourcePath = "",
|
|
173
|
+
options,
|
|
174
|
+
shouldPrintDebug = !1
|
|
175
|
+
} = params;
|
|
176
|
+
if (typeof source != "string") throw new Error("`source` must be a string of javascript");
|
|
177
|
+
const task = {
|
|
178
|
+
type: "extractToClassNames",
|
|
179
|
+
source,
|
|
180
|
+
sourcePath,
|
|
181
|
+
options,
|
|
182
|
+
shouldPrintDebug
|
|
183
|
+
},
|
|
184
|
+
result = await getPool().run(task, {
|
|
185
|
+
name: "runTask"
|
|
186
|
+
});
|
|
187
|
+
if (!result.success) {
|
|
188
|
+
const errorMessage = [`[gui-extract] Error processing file: ${sourcePath || "(unknown)"}`, "", result.error, result.stack ? `
|
|
189
|
+
${result.stack}` : ""].filter(Boolean).join(`
|
|
190
|
+
`);
|
|
191
|
+
throw new Error(errorMessage);
|
|
192
|
+
}
|
|
193
|
+
return incrementTaskCount() >= MAX_TASKS_BEFORE_RECYCLE && (resetTaskCount(), recyclePool(options).catch(() => {})), result.data;
|
|
194
|
+
}
|
|
195
|
+
async function extractToNative(sourceFileName, sourceCode, options) {
|
|
196
|
+
const task = {
|
|
197
|
+
type: "extractToNative",
|
|
198
|
+
sourceFileName,
|
|
199
|
+
sourceCode,
|
|
200
|
+
options
|
|
201
|
+
},
|
|
202
|
+
result = await getPool().run(task, {
|
|
203
|
+
name: "runTask"
|
|
204
|
+
});
|
|
205
|
+
if (!result.success) {
|
|
206
|
+
const errorMessage = [`[gui-extract] Error processing file: ${sourceFileName || "(unknown)"}`, "", result.error, result.stack ? `
|
|
207
|
+
${result.stack}` : ""].filter(Boolean).join(`
|
|
208
|
+
`);
|
|
209
|
+
throw new Error(errorMessage);
|
|
210
|
+
}
|
|
211
|
+
return incrementTaskCount() >= MAX_TASKS_BEFORE_RECYCLE && (resetTaskCount(), recyclePool(options).catch(() => {})), result.data;
|
|
212
|
+
}
|
|
213
|
+
async function watchGuiConfig(options) {
|
|
214
|
+
const {
|
|
215
|
+
default: Static
|
|
216
|
+
} = await import("@hanzogui/static"),
|
|
217
|
+
watcher = await Static.watchGuiConfig(options);
|
|
218
|
+
if (!watcher) return;
|
|
219
|
+
const originalDispose = watcher.dispose;
|
|
220
|
+
return {
|
|
221
|
+
dispose: () => {
|
|
222
|
+
originalDispose(), getSharedPool() && clearWorkerCache();
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
async function clearWorkerCache() {
|
|
227
|
+
const pool = getSharedPool();
|
|
228
|
+
if (!pool || isClosing()) return;
|
|
229
|
+
const task = {
|
|
230
|
+
type: "clearCache"
|
|
231
|
+
};
|
|
232
|
+
await pool.run(task, {
|
|
233
|
+
name: "runTask"
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
async function destroyPool() {
|
|
237
|
+
const pool = getSharedPool();
|
|
238
|
+
if (pool) {
|
|
239
|
+
setClosing(!0);
|
|
240
|
+
try {
|
|
241
|
+
await pool.close();
|
|
242
|
+
} finally {
|
|
243
|
+
setSharedPool(null), setClosing(!1);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function getPoolStats() {
|
|
248
|
+
const pool = getSharedPool();
|
|
249
|
+
return pool ? {
|
|
250
|
+
threads: pool.threads.length,
|
|
251
|
+
queueSize: pool.queueSize,
|
|
252
|
+
completed: pool.completed,
|
|
253
|
+
duration: pool.duration,
|
|
254
|
+
utilization: pool.utilization
|
|
255
|
+
} : null;
|
|
256
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import Piscina from "piscina";
|
|
3
|
+
const getPragmaOptions = async props => {
|
|
4
|
+
const {
|
|
5
|
+
default: Static
|
|
6
|
+
} = await import("@hanzogui/static");
|
|
7
|
+
return Static.getPragmaOptions(props);
|
|
8
|
+
},
|
|
9
|
+
getWorkerPath = () => typeof import.meta < "u" && import.meta.url ? fileURLToPath(import.meta.resolve("@hanzogui/static/worker")).replace(/\.mjs$/, ".js") : require.resolve("@hanzogui/static/worker").replace(/\.mjs$/, ".js"),
|
|
10
|
+
POOL_KEY = "__gui_piscina_pool__",
|
|
11
|
+
CLOSING_KEY = "__gui_piscina_closing__",
|
|
12
|
+
TASK_COUNT_KEY = "__gui_piscina_task_count__",
|
|
13
|
+
RECYCLING_KEY = "__gui_piscina_recycling__",
|
|
14
|
+
MAX_TASKS_BEFORE_RECYCLE = 1e3;
|
|
15
|
+
function getSharedPool() {
|
|
16
|
+
return globalThis[POOL_KEY] ?? null;
|
|
17
|
+
}
|
|
18
|
+
function setSharedPool(pool) {
|
|
19
|
+
globalThis[POOL_KEY] = pool;
|
|
20
|
+
}
|
|
21
|
+
function isClosing() {
|
|
22
|
+
return globalThis[CLOSING_KEY] === !0;
|
|
23
|
+
}
|
|
24
|
+
function setClosing(value) {
|
|
25
|
+
globalThis[CLOSING_KEY] = value;
|
|
26
|
+
}
|
|
27
|
+
function isRecycling() {
|
|
28
|
+
return globalThis[RECYCLING_KEY] === !0;
|
|
29
|
+
}
|
|
30
|
+
function setRecycling(value) {
|
|
31
|
+
globalThis[RECYCLING_KEY] = value;
|
|
32
|
+
}
|
|
33
|
+
function getTaskCount() {
|
|
34
|
+
return globalThis[TASK_COUNT_KEY] ?? 0;
|
|
35
|
+
}
|
|
36
|
+
function incrementTaskCount() {
|
|
37
|
+
const count = getTaskCount() + 1;
|
|
38
|
+
return globalThis[TASK_COUNT_KEY] = count, count;
|
|
39
|
+
}
|
|
40
|
+
function resetTaskCount() {
|
|
41
|
+
globalThis[TASK_COUNT_KEY] = 0;
|
|
42
|
+
}
|
|
43
|
+
function createPool() {
|
|
44
|
+
const pool = new Piscina({
|
|
45
|
+
filename: getWorkerPath(),
|
|
46
|
+
// each worker loads and caches config independently
|
|
47
|
+
minThreads: 2,
|
|
48
|
+
maxThreads: 2,
|
|
49
|
+
// Never terminate due to idle - worker stays alive until close() or process exit
|
|
50
|
+
// This prevents "Terminating worker thread" errors from Piscina during idle
|
|
51
|
+
idleTimeout: Number.POSITIVE_INFINITY
|
|
52
|
+
// no resourceLimits - we rely on task-based recycling instead
|
|
53
|
+
// V8 resourceLimits cause "Terminating worker thread" messages when hit
|
|
54
|
+
});
|
|
55
|
+
return pool.on("error", err => {
|
|
56
|
+
isClosing() || isRecycling() || (err && typeof err == "object" && "message" in err ? String(err.message) : "").includes("Terminating worker thread") || console.error("[hanzo-gui] Worker pool error:", err);
|
|
57
|
+
}), pool;
|
|
58
|
+
}
|
|
59
|
+
function getPool() {
|
|
60
|
+
let pool = getSharedPool();
|
|
61
|
+
return pool || (pool = createPool(), setSharedPool(pool)), pool;
|
|
62
|
+
}
|
|
63
|
+
async function loadGui(options) {
|
|
64
|
+
const pool = getPool(),
|
|
65
|
+
task = {
|
|
66
|
+
type: "extractToClassNames",
|
|
67
|
+
source: "// dummy",
|
|
68
|
+
sourcePath: "__dummy__.tsx",
|
|
69
|
+
options: {
|
|
70
|
+
components: ["@hanzo/gui"],
|
|
71
|
+
...options
|
|
72
|
+
},
|
|
73
|
+
shouldPrintDebug: !1
|
|
74
|
+
};
|
|
75
|
+
try {
|
|
76
|
+
return await pool.run(task, {
|
|
77
|
+
name: "runTask"
|
|
78
|
+
}), {
|
|
79
|
+
success: !0
|
|
80
|
+
};
|
|
81
|
+
} catch (error) {
|
|
82
|
+
throw console.error("[static-worker] Error loading Hanzo GUI config:", error), error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function recyclePool(options) {
|
|
86
|
+
if (isClosing() || isRecycling()) return;
|
|
87
|
+
const oldPool = getSharedPool();
|
|
88
|
+
if (!oldPool) return;
|
|
89
|
+
setRecycling(!0);
|
|
90
|
+
const start = Date.now();
|
|
91
|
+
try {
|
|
92
|
+
const originalStderr = process.stderr.write.bind(process.stderr),
|
|
93
|
+
originalStdout = process.stdout.write.bind(process.stdout),
|
|
94
|
+
filter = (chunk, ...args) => !!(typeof chunk == "string" ? chunk : chunk?.toString?.() || "").includes("Terminating worker thread");
|
|
95
|
+
process.stderr.write = (chunk, ...args) => filter(chunk) ? !0 : originalStderr(chunk, ...args), process.stdout.write = (chunk, ...args) => filter(chunk) ? !0 : originalStdout(chunk, ...args);
|
|
96
|
+
const newPool = createPool();
|
|
97
|
+
setSharedPool(newPool);
|
|
98
|
+
const warmupTask = {
|
|
99
|
+
type: "extractToClassNames",
|
|
100
|
+
source: "// warmup",
|
|
101
|
+
sourcePath: "__warmup__.tsx",
|
|
102
|
+
options: {
|
|
103
|
+
...options,
|
|
104
|
+
// skip the "built config" log on warmup since it's a recycle
|
|
105
|
+
_skipBuildLog: !0
|
|
106
|
+
},
|
|
107
|
+
shouldPrintDebug: !1
|
|
108
|
+
};
|
|
109
|
+
await newPool.run(warmupTask, {
|
|
110
|
+
name: "runTask"
|
|
111
|
+
}), oldPool.removeAllListeners(), oldPool.destroy().catch(() => {}), setTimeout(() => {
|
|
112
|
+
process.stderr.write = originalStderr, process.stdout.write = originalStdout;
|
|
113
|
+
}), console.log(` \u267B\uFE0F [hanzo-gui] recycled worker pool (${Date.now() - start}ms)`);
|
|
114
|
+
} finally {
|
|
115
|
+
setRecycling(!1);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function loadGuiBuildConfig(guiOptions) {
|
|
119
|
+
const {
|
|
120
|
+
default: Static
|
|
121
|
+
} = await import("@hanzogui/static");
|
|
122
|
+
return Static.loadGuiBuildConfigAsync(guiOptions);
|
|
123
|
+
}
|
|
124
|
+
async function extractToClassNames(params) {
|
|
125
|
+
const {
|
|
126
|
+
source,
|
|
127
|
+
sourcePath = "",
|
|
128
|
+
options,
|
|
129
|
+
shouldPrintDebug = !1
|
|
130
|
+
} = params;
|
|
131
|
+
if (typeof source != "string") throw new Error("`source` must be a string of javascript");
|
|
132
|
+
const task = {
|
|
133
|
+
type: "extractToClassNames",
|
|
134
|
+
source,
|
|
135
|
+
sourcePath,
|
|
136
|
+
options,
|
|
137
|
+
shouldPrintDebug
|
|
138
|
+
},
|
|
139
|
+
result = await getPool().run(task, {
|
|
140
|
+
name: "runTask"
|
|
141
|
+
});
|
|
142
|
+
if (!result.success) {
|
|
143
|
+
const errorMessage = [`[gui-extract] Error processing file: ${sourcePath || "(unknown)"}`, "", result.error, result.stack ? `
|
|
144
|
+
${result.stack}` : ""].filter(Boolean).join(`
|
|
145
|
+
`);
|
|
146
|
+
throw new Error(errorMessage);
|
|
147
|
+
}
|
|
148
|
+
return incrementTaskCount() >= MAX_TASKS_BEFORE_RECYCLE && (resetTaskCount(), recyclePool(options).catch(() => {})), result.data;
|
|
149
|
+
}
|
|
150
|
+
async function extractToNative(sourceFileName, sourceCode, options) {
|
|
151
|
+
const task = {
|
|
152
|
+
type: "extractToNative",
|
|
153
|
+
sourceFileName,
|
|
154
|
+
sourceCode,
|
|
155
|
+
options
|
|
156
|
+
},
|
|
157
|
+
result = await getPool().run(task, {
|
|
158
|
+
name: "runTask"
|
|
159
|
+
});
|
|
160
|
+
if (!result.success) {
|
|
161
|
+
const errorMessage = [`[gui-extract] Error processing file: ${sourceFileName || "(unknown)"}`, "", result.error, result.stack ? `
|
|
162
|
+
${result.stack}` : ""].filter(Boolean).join(`
|
|
163
|
+
`);
|
|
164
|
+
throw new Error(errorMessage);
|
|
165
|
+
}
|
|
166
|
+
return incrementTaskCount() >= MAX_TASKS_BEFORE_RECYCLE && (resetTaskCount(), recyclePool(options).catch(() => {})), result.data;
|
|
167
|
+
}
|
|
168
|
+
async function watchGuiConfig(options) {
|
|
169
|
+
const {
|
|
170
|
+
default: Static
|
|
171
|
+
} = await import("@hanzogui/static"),
|
|
172
|
+
watcher = await Static.watchGuiConfig(options);
|
|
173
|
+
if (!watcher) return;
|
|
174
|
+
const originalDispose = watcher.dispose;
|
|
175
|
+
return {
|
|
176
|
+
dispose: () => {
|
|
177
|
+
originalDispose(), getSharedPool() && clearWorkerCache();
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
async function clearWorkerCache() {
|
|
182
|
+
const pool = getSharedPool();
|
|
183
|
+
if (!pool || isClosing()) return;
|
|
184
|
+
const task = {
|
|
185
|
+
type: "clearCache"
|
|
186
|
+
};
|
|
187
|
+
await pool.run(task, {
|
|
188
|
+
name: "runTask"
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
async function destroyPool() {
|
|
192
|
+
const pool = getSharedPool();
|
|
193
|
+
if (pool) {
|
|
194
|
+
setClosing(!0);
|
|
195
|
+
try {
|
|
196
|
+
await pool.close();
|
|
197
|
+
} finally {
|
|
198
|
+
setSharedPool(null), setClosing(!1);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function getPoolStats() {
|
|
203
|
+
const pool = getSharedPool();
|
|
204
|
+
return pool ? {
|
|
205
|
+
threads: pool.threads.length,
|
|
206
|
+
queueSize: pool.queueSize,
|
|
207
|
+
completed: pool.completed,
|
|
208
|
+
duration: pool.duration,
|
|
209
|
+
utilization: pool.utilization
|
|
210
|
+
} : null;
|
|
211
|
+
}
|
|
212
|
+
export { clearWorkerCache, destroyPool, extractToClassNames, extractToNative, getPoolStats, getPragmaOptions, loadGui, loadGuiBuildConfig, watchGuiConfig };
|
|
213
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["fileURLToPath","Piscina","getPragmaOptions","props","default","Static","getWorkerPath","import","meta","url","resolve","replace","require","POOL_KEY","CLOSING_KEY","TASK_COUNT_KEY","RECYCLING_KEY","MAX_TASKS_BEFORE_RECYCLE","getSharedPool","globalThis","setSharedPool","pool","isClosing","setClosing","value","isRecycling","setRecycling","getTaskCount","incrementTaskCount","count","resetTaskCount","createPool","filename","minThreads","maxThreads","idleTimeout","Number","POSITIVE_INFINITY","on","err","String","message","includes","console","error","getPool","loadGui","options","task","type","source","sourcePath","components","shouldPrintDebug","run","name","success","recyclePool","oldPool","start","Date","now","originalStderr","process","stderr","write","bind","originalStdout","stdout","filter","chunk","args","toString","newPool","warmupTask","_skipBuildLog","removeAllListeners","destroy","catch","setTimeout","log","loadGuiBuildConfig","guiOptions","loadGuiBuildConfigAsync","extractToClassNames","params","Error","result","errorMessage","stack","Boolean","join","data","extractToNative","sourceFileName","sourceCode","watchGuiConfig","watcher","originalDispose","dispose","clearWorkerCache","destroyPool","close","getPoolStats","threads","length","queueSize","completed","duration","utilization"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import Piscina from "piscina";
|
|
3
|
+
const getPragmaOptions = async props => {
|
|
4
|
+
const {
|
|
5
|
+
default: Static
|
|
6
|
+
} = await import("@hanzogui/static");
|
|
7
|
+
return Static.getPragmaOptions(props);
|
|
8
|
+
},
|
|
9
|
+
getWorkerPath = () => typeof import.meta < "u" && import.meta.url ? fileURLToPath(import.meta.resolve("@hanzogui/static/worker")).replace(/\.mjs$/, ".js") : require.resolve("@hanzogui/static/worker").replace(/\.mjs$/, ".js"),
|
|
10
|
+
POOL_KEY = "__gui_piscina_pool__",
|
|
11
|
+
CLOSING_KEY = "__gui_piscina_closing__",
|
|
12
|
+
TASK_COUNT_KEY = "__gui_piscina_task_count__",
|
|
13
|
+
RECYCLING_KEY = "__gui_piscina_recycling__",
|
|
14
|
+
MAX_TASKS_BEFORE_RECYCLE = 1e3;
|
|
15
|
+
function getSharedPool() {
|
|
16
|
+
return globalThis[POOL_KEY] ?? null;
|
|
17
|
+
}
|
|
18
|
+
function setSharedPool(pool) {
|
|
19
|
+
globalThis[POOL_KEY] = pool;
|
|
20
|
+
}
|
|
21
|
+
function isClosing() {
|
|
22
|
+
return globalThis[CLOSING_KEY] === !0;
|
|
23
|
+
}
|
|
24
|
+
function setClosing(value) {
|
|
25
|
+
globalThis[CLOSING_KEY] = value;
|
|
26
|
+
}
|
|
27
|
+
function isRecycling() {
|
|
28
|
+
return globalThis[RECYCLING_KEY] === !0;
|
|
29
|
+
}
|
|
30
|
+
function setRecycling(value) {
|
|
31
|
+
globalThis[RECYCLING_KEY] = value;
|
|
32
|
+
}
|
|
33
|
+
function getTaskCount() {
|
|
34
|
+
return globalThis[TASK_COUNT_KEY] ?? 0;
|
|
35
|
+
}
|
|
36
|
+
function incrementTaskCount() {
|
|
37
|
+
const count = getTaskCount() + 1;
|
|
38
|
+
return globalThis[TASK_COUNT_KEY] = count, count;
|
|
39
|
+
}
|
|
40
|
+
function resetTaskCount() {
|
|
41
|
+
globalThis[TASK_COUNT_KEY] = 0;
|
|
42
|
+
}
|
|
43
|
+
function createPool() {
|
|
44
|
+
const pool = new Piscina({
|
|
45
|
+
filename: getWorkerPath(),
|
|
46
|
+
// each worker loads and caches config independently
|
|
47
|
+
minThreads: 2,
|
|
48
|
+
maxThreads: 2,
|
|
49
|
+
// Never terminate due to idle - worker stays alive until close() or process exit
|
|
50
|
+
// This prevents "Terminating worker thread" errors from Piscina during idle
|
|
51
|
+
idleTimeout: Number.POSITIVE_INFINITY
|
|
52
|
+
// no resourceLimits - we rely on task-based recycling instead
|
|
53
|
+
// V8 resourceLimits cause "Terminating worker thread" messages when hit
|
|
54
|
+
});
|
|
55
|
+
return pool.on("error", err => {
|
|
56
|
+
isClosing() || isRecycling() || (err && typeof err == "object" && "message" in err ? String(err.message) : "").includes("Terminating worker thread") || console.error("[hanzo-gui] Worker pool error:", err);
|
|
57
|
+
}), pool;
|
|
58
|
+
}
|
|
59
|
+
function getPool() {
|
|
60
|
+
let pool = getSharedPool();
|
|
61
|
+
return pool || (pool = createPool(), setSharedPool(pool)), pool;
|
|
62
|
+
}
|
|
63
|
+
async function loadGui(options) {
|
|
64
|
+
const pool = getPool(),
|
|
65
|
+
task = {
|
|
66
|
+
type: "extractToClassNames",
|
|
67
|
+
source: "// dummy",
|
|
68
|
+
sourcePath: "__dummy__.tsx",
|
|
69
|
+
options: {
|
|
70
|
+
components: ["@hanzo/gui"],
|
|
71
|
+
...options
|
|
72
|
+
},
|
|
73
|
+
shouldPrintDebug: !1
|
|
74
|
+
};
|
|
75
|
+
try {
|
|
76
|
+
return await pool.run(task, {
|
|
77
|
+
name: "runTask"
|
|
78
|
+
}), {
|
|
79
|
+
success: !0
|
|
80
|
+
};
|
|
81
|
+
} catch (error) {
|
|
82
|
+
throw console.error("[static-worker] Error loading Hanzo GUI config:", error), error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function recyclePool(options) {
|
|
86
|
+
if (isClosing() || isRecycling()) return;
|
|
87
|
+
const oldPool = getSharedPool();
|
|
88
|
+
if (!oldPool) return;
|
|
89
|
+
setRecycling(!0);
|
|
90
|
+
const start = Date.now();
|
|
91
|
+
try {
|
|
92
|
+
const originalStderr = process.stderr.write.bind(process.stderr),
|
|
93
|
+
originalStdout = process.stdout.write.bind(process.stdout),
|
|
94
|
+
filter = (chunk, ...args) => !!(typeof chunk == "string" ? chunk : chunk?.toString?.() || "").includes("Terminating worker thread");
|
|
95
|
+
process.stderr.write = (chunk, ...args) => filter(chunk) ? !0 : originalStderr(chunk, ...args), process.stdout.write = (chunk, ...args) => filter(chunk) ? !0 : originalStdout(chunk, ...args);
|
|
96
|
+
const newPool = createPool();
|
|
97
|
+
setSharedPool(newPool);
|
|
98
|
+
const warmupTask = {
|
|
99
|
+
type: "extractToClassNames",
|
|
100
|
+
source: "// warmup",
|
|
101
|
+
sourcePath: "__warmup__.tsx",
|
|
102
|
+
options: {
|
|
103
|
+
...options,
|
|
104
|
+
// skip the "built config" log on warmup since it's a recycle
|
|
105
|
+
_skipBuildLog: !0
|
|
106
|
+
},
|
|
107
|
+
shouldPrintDebug: !1
|
|
108
|
+
};
|
|
109
|
+
await newPool.run(warmupTask, {
|
|
110
|
+
name: "runTask"
|
|
111
|
+
}), oldPool.removeAllListeners(), oldPool.destroy().catch(() => {}), setTimeout(() => {
|
|
112
|
+
process.stderr.write = originalStderr, process.stdout.write = originalStdout;
|
|
113
|
+
}), console.log(` \u267B\uFE0F [hanzo-gui] recycled worker pool (${Date.now() - start}ms)`);
|
|
114
|
+
} finally {
|
|
115
|
+
setRecycling(!1);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function loadGuiBuildConfig(guiOptions) {
|
|
119
|
+
const {
|
|
120
|
+
default: Static
|
|
121
|
+
} = await import("@hanzogui/static");
|
|
122
|
+
return Static.loadGuiBuildConfigAsync(guiOptions);
|
|
123
|
+
}
|
|
124
|
+
async function extractToClassNames(params) {
|
|
125
|
+
const {
|
|
126
|
+
source,
|
|
127
|
+
sourcePath = "",
|
|
128
|
+
options,
|
|
129
|
+
shouldPrintDebug = !1
|
|
130
|
+
} = params;
|
|
131
|
+
if (typeof source != "string") throw new Error("`source` must be a string of javascript");
|
|
132
|
+
const task = {
|
|
133
|
+
type: "extractToClassNames",
|
|
134
|
+
source,
|
|
135
|
+
sourcePath,
|
|
136
|
+
options,
|
|
137
|
+
shouldPrintDebug
|
|
138
|
+
},
|
|
139
|
+
result = await getPool().run(task, {
|
|
140
|
+
name: "runTask"
|
|
141
|
+
});
|
|
142
|
+
if (!result.success) {
|
|
143
|
+
const errorMessage = [`[gui-extract] Error processing file: ${sourcePath || "(unknown)"}`, "", result.error, result.stack ? `
|
|
144
|
+
${result.stack}` : ""].filter(Boolean).join(`
|
|
145
|
+
`);
|
|
146
|
+
throw new Error(errorMessage);
|
|
147
|
+
}
|
|
148
|
+
return incrementTaskCount() >= MAX_TASKS_BEFORE_RECYCLE && (resetTaskCount(), recyclePool(options).catch(() => {})), result.data;
|
|
149
|
+
}
|
|
150
|
+
async function extractToNative(sourceFileName, sourceCode, options) {
|
|
151
|
+
const task = {
|
|
152
|
+
type: "extractToNative",
|
|
153
|
+
sourceFileName,
|
|
154
|
+
sourceCode,
|
|
155
|
+
options
|
|
156
|
+
},
|
|
157
|
+
result = await getPool().run(task, {
|
|
158
|
+
name: "runTask"
|
|
159
|
+
});
|
|
160
|
+
if (!result.success) {
|
|
161
|
+
const errorMessage = [`[gui-extract] Error processing file: ${sourceFileName || "(unknown)"}`, "", result.error, result.stack ? `
|
|
162
|
+
${result.stack}` : ""].filter(Boolean).join(`
|
|
163
|
+
`);
|
|
164
|
+
throw new Error(errorMessage);
|
|
165
|
+
}
|
|
166
|
+
return incrementTaskCount() >= MAX_TASKS_BEFORE_RECYCLE && (resetTaskCount(), recyclePool(options).catch(() => {})), result.data;
|
|
167
|
+
}
|
|
168
|
+
async function watchGuiConfig(options) {
|
|
169
|
+
const {
|
|
170
|
+
default: Static
|
|
171
|
+
} = await import("@hanzogui/static"),
|
|
172
|
+
watcher = await Static.watchGuiConfig(options);
|
|
173
|
+
if (!watcher) return;
|
|
174
|
+
const originalDispose = watcher.dispose;
|
|
175
|
+
return {
|
|
176
|
+
dispose: () => {
|
|
177
|
+
originalDispose(), getSharedPool() && clearWorkerCache();
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
async function clearWorkerCache() {
|
|
182
|
+
const pool = getSharedPool();
|
|
183
|
+
if (!pool || isClosing()) return;
|
|
184
|
+
const task = {
|
|
185
|
+
type: "clearCache"
|
|
186
|
+
};
|
|
187
|
+
await pool.run(task, {
|
|
188
|
+
name: "runTask"
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
async function destroyPool() {
|
|
192
|
+
const pool = getSharedPool();
|
|
193
|
+
if (pool) {
|
|
194
|
+
setClosing(!0);
|
|
195
|
+
try {
|
|
196
|
+
await pool.close();
|
|
197
|
+
} finally {
|
|
198
|
+
setSharedPool(null), setClosing(!1);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function getPoolStats() {
|
|
203
|
+
const pool = getSharedPool();
|
|
204
|
+
return pool ? {
|
|
205
|
+
threads: pool.threads.length,
|
|
206
|
+
queueSize: pool.queueSize,
|
|
207
|
+
completed: pool.completed,
|
|
208
|
+
duration: pool.duration,
|
|
209
|
+
utilization: pool.utilization
|
|
210
|
+
} : null;
|
|
211
|
+
}
|
|
212
|
+
export { clearWorkerCache, destroyPool, extractToClassNames, extractToNative, getPoolStats, getPragmaOptions, loadGui, loadGuiBuildConfig, watchGuiConfig };
|
|
213
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["fileURLToPath","Piscina","getPragmaOptions","props","default","Static","getWorkerPath","import","meta","url","resolve","replace","require","POOL_KEY","CLOSING_KEY","TASK_COUNT_KEY","RECYCLING_KEY","MAX_TASKS_BEFORE_RECYCLE","getSharedPool","globalThis","setSharedPool","pool","isClosing","setClosing","value","isRecycling","setRecycling","getTaskCount","incrementTaskCount","count","resetTaskCount","createPool","filename","minThreads","maxThreads","idleTimeout","Number","POSITIVE_INFINITY","on","err","String","message","includes","console","error","getPool","loadGui","options","task","type","source","sourcePath","components","shouldPrintDebug","run","name","success","recyclePool","oldPool","start","Date","now","originalStderr","process","stderr","write","bind","originalStdout","stdout","filter","chunk","args","toString","newPool","warmupTask","_skipBuildLog","removeAllListeners","destroy","catch","setTimeout","log","loadGuiBuildConfig","guiOptions","loadGuiBuildConfigAsync","extractToClassNames","params","Error","result","errorMessage","stack","Boolean","join","data","extractToNative","sourceFileName","sourceCode","watchGuiConfig","watcher","originalDispose","dispose","clearWorkerCache","destroyPool","close","getPoolStats","threads","length","queueSize","completed","duration","utilization"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hanzogui/static-worker",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"source": "src/index.ts",
|
|
6
|
+
"files": [
|
|
7
|
+
"src",
|
|
8
|
+
"types",
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "dist/cjs",
|
|
13
|
+
"module": "dist/esm",
|
|
14
|
+
"types": "./types/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
"./package.json": "./package.json",
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./types/index.d.ts",
|
|
19
|
+
"browser": "./dist/esm/index.mjs",
|
|
20
|
+
"module": "./dist/esm/index.mjs",
|
|
21
|
+
"import": "./dist/esm/index.mjs",
|
|
22
|
+
"require": "./dist/cjs/index.cjs"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "hanzo-gui-build --skip-native",
|
|
30
|
+
"watch": "hanzo-gui-build --skip-native --watch",
|
|
31
|
+
"clean": "hanzo-gui-build clean",
|
|
32
|
+
"clean:build": "hanzo-gui-build clean:build",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test:web": "bun run test",
|
|
35
|
+
"test:watch": "vitest"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@hanzogui/static": "workspace:*",
|
|
39
|
+
"@hanzogui/types": "workspace:*",
|
|
40
|
+
"piscina": "^4.7.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@hanzogui/build": "workspace:*",
|
|
44
|
+
"vitest": "4.0.4"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hanzogui/static-worker
|
|
3
|
+
*
|
|
4
|
+
* Pure worker-based API for Hanzo GUI static extraction.
|
|
5
|
+
* All operations run in a worker thread for better performance and isolation.
|
|
6
|
+
*
|
|
7
|
+
* This package provides a clean async API that wraps @hanzogui/static's worker
|
|
8
|
+
* implementation without exposing any sync/legacy APIs.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { GuiOptions } from '@hanzogui/types'
|
|
12
|
+
import { fileURLToPath } from 'node:url'
|
|
13
|
+
import Piscina from 'piscina'
|
|
14
|
+
|
|
15
|
+
export type { ExtractedResponse, GuiProjectInfo } from '@hanzogui/static'
|
|
16
|
+
export type { GuiOptions } from '@hanzogui/types'
|
|
17
|
+
|
|
18
|
+
export const getPragmaOptions = async (props: { source: string; path: string }) => {
|
|
19
|
+
const { default: Static } = await import('@hanzogui/static')
|
|
20
|
+
return Static.getPragmaOptions(props)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Resolve worker path - works for both CJS and ESM
|
|
24
|
+
const getWorkerPath = () => {
|
|
25
|
+
// Piscina needs the actual file path, not the module resolution
|
|
26
|
+
// Use the CommonJS .js version which works for piscina
|
|
27
|
+
if (typeof import.meta !== 'undefined' && import.meta.url) {
|
|
28
|
+
const workerPath = fileURLToPath(import.meta.resolve('@hanzogui/static/worker'))
|
|
29
|
+
// Replace .mjs with .js for CommonJS compatibility
|
|
30
|
+
return workerPath.replace(/\.mjs$/, '.js')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Fallback for CJS
|
|
34
|
+
return require.resolve('@hanzogui/static/worker').replace(/\.mjs$/, '.js')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Use globalThis to share pool across module instances (Vite environments)
|
|
38
|
+
const POOL_KEY = '__gui_piscina_pool__'
|
|
39
|
+
const CLOSING_KEY = '__gui_piscina_closing__'
|
|
40
|
+
const TASK_COUNT_KEY = '__gui_piscina_task_count__'
|
|
41
|
+
const RECYCLING_KEY = '__gui_piscina_recycling__'
|
|
42
|
+
|
|
43
|
+
// recycle worker after this many tasks to prevent RSS bloat from V8 memory fragmentation
|
|
44
|
+
// Node.js worker threads don't release memory properly - see https://github.com/nodejs/node/issues/51868
|
|
45
|
+
// set high enough that builds (typically 200-400 files) never trigger a recycle,
|
|
46
|
+
// but long-running dev servers still get memory relief eventually
|
|
47
|
+
const MAX_TASKS_BEFORE_RECYCLE = 1000
|
|
48
|
+
|
|
49
|
+
function getSharedPool(): Piscina | null {
|
|
50
|
+
return (globalThis as any)[POOL_KEY] ?? null
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function setSharedPool(pool: Piscina | null) {
|
|
54
|
+
;(globalThis as any)[POOL_KEY] = pool
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function isClosing(): boolean {
|
|
58
|
+
return (globalThis as any)[CLOSING_KEY] === true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function setClosing(value: boolean) {
|
|
62
|
+
;(globalThis as any)[CLOSING_KEY] = value
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function isRecycling(): boolean {
|
|
66
|
+
return (globalThis as any)[RECYCLING_KEY] === true
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function setRecycling(value: boolean) {
|
|
70
|
+
;(globalThis as any)[RECYCLING_KEY] = value
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getTaskCount(): number {
|
|
74
|
+
return (globalThis as any)[TASK_COUNT_KEY] ?? 0
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function incrementTaskCount(): number {
|
|
78
|
+
const count = getTaskCount() + 1
|
|
79
|
+
;(globalThis as any)[TASK_COUNT_KEY] = count
|
|
80
|
+
return count
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function resetTaskCount() {
|
|
84
|
+
;(globalThis as any)[TASK_COUNT_KEY] = 0
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create a new Piscina pool instance
|
|
89
|
+
*/
|
|
90
|
+
function createPool(): Piscina {
|
|
91
|
+
const pool = new Piscina({
|
|
92
|
+
filename: getWorkerPath(),
|
|
93
|
+
// each worker loads and caches config independently
|
|
94
|
+
minThreads: 2,
|
|
95
|
+
maxThreads: 2,
|
|
96
|
+
// Never terminate due to idle - worker stays alive until close() or process exit
|
|
97
|
+
// This prevents "Terminating worker thread" errors from Piscina during idle
|
|
98
|
+
idleTimeout: Number.POSITIVE_INFINITY,
|
|
99
|
+
// no resourceLimits - we rely on task-based recycling instead
|
|
100
|
+
// V8 resourceLimits cause "Terminating worker thread" messages when hit
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
// Handle error events to prevent uncaught exceptions during pool destruction
|
|
104
|
+
pool.on('error', (err) => {
|
|
105
|
+
if (isClosing() || isRecycling()) return
|
|
106
|
+
const message =
|
|
107
|
+
err && typeof err === 'object' && 'message' in err ? String(err.message) : ''
|
|
108
|
+
// Suppress termination errors (can still occur during explicit close/destroy)
|
|
109
|
+
if (message.includes('Terminating worker thread')) return
|
|
110
|
+
console.error('[hanzo-gui] Worker pool error:', err)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
return pool
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get or create the Piscina worker pool
|
|
118
|
+
*/
|
|
119
|
+
function getPool(): Piscina {
|
|
120
|
+
let pool = getSharedPool()
|
|
121
|
+
if (!pool) {
|
|
122
|
+
pool = createPool()
|
|
123
|
+
setSharedPool(pool)
|
|
124
|
+
}
|
|
125
|
+
return pool
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Load Hanzo GUI configuration in worker
|
|
130
|
+
* Sends a warmup task to trigger config loading
|
|
131
|
+
* bundleConfig auto-detects if files exist and skips rebuild
|
|
132
|
+
*/
|
|
133
|
+
export async function loadGui(options: Partial<GuiOptions>): Promise<any> {
|
|
134
|
+
const pool = getPool()
|
|
135
|
+
|
|
136
|
+
// use extractToClassNames with a dummy request to trigger config loading
|
|
137
|
+
// the worker will cache the config for subsequent requests
|
|
138
|
+
const task = {
|
|
139
|
+
type: 'extractToClassNames',
|
|
140
|
+
source: '// dummy',
|
|
141
|
+
sourcePath: '__dummy__.tsx',
|
|
142
|
+
options: {
|
|
143
|
+
components: ['@hanzo/gui'],
|
|
144
|
+
...options,
|
|
145
|
+
},
|
|
146
|
+
shouldPrintDebug: false,
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
await pool.run(task, { name: 'runTask' })
|
|
151
|
+
return { success: true }
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error('[static-worker] Error loading Hanzo GUI config:', error)
|
|
154
|
+
throw error
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Recycle the worker pool to release RSS memory
|
|
160
|
+
* Creates new pool, swaps immediately, then destroys old pool
|
|
161
|
+
* V8 doesn't return memory to OS, so we need to restart the worker periodically
|
|
162
|
+
*/
|
|
163
|
+
async function recyclePool(options: GuiOptions): Promise<void> {
|
|
164
|
+
if (isClosing() || isRecycling()) return
|
|
165
|
+
|
|
166
|
+
const oldPool = getSharedPool()
|
|
167
|
+
if (!oldPool) return
|
|
168
|
+
|
|
169
|
+
setRecycling(true)
|
|
170
|
+
|
|
171
|
+
const start = Date.now()
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
// suppress "Terminating worker thread" messages during recycle
|
|
175
|
+
const originalStderr = process.stderr.write.bind(process.stderr)
|
|
176
|
+
const originalStdout = process.stdout.write.bind(process.stdout)
|
|
177
|
+
const filter = (chunk: any, ...args: any[]) => {
|
|
178
|
+
const str = typeof chunk === 'string' ? chunk : chunk?.toString?.() || ''
|
|
179
|
+
if (str.includes('Terminating worker thread')) return true
|
|
180
|
+
return false
|
|
181
|
+
}
|
|
182
|
+
process.stderr.write = ((chunk: any, ...args: any[]) => {
|
|
183
|
+
if (filter(chunk)) return true
|
|
184
|
+
return originalStderr(chunk, ...args)
|
|
185
|
+
}) as any
|
|
186
|
+
process.stdout.write = ((chunk: any, ...args: any[]) => {
|
|
187
|
+
if (filter(chunk)) return true
|
|
188
|
+
return originalStdout(chunk, ...args)
|
|
189
|
+
}) as any
|
|
190
|
+
|
|
191
|
+
// create new pool and swap immediately
|
|
192
|
+
const newPool = createPool()
|
|
193
|
+
setSharedPool(newPool)
|
|
194
|
+
|
|
195
|
+
// warm up new pool with config (this caches it in the new worker)
|
|
196
|
+
const warmupTask = {
|
|
197
|
+
type: 'extractToClassNames',
|
|
198
|
+
source: '// warmup',
|
|
199
|
+
sourcePath: '__warmup__.tsx',
|
|
200
|
+
options: {
|
|
201
|
+
...options,
|
|
202
|
+
// skip the "built config" log on warmup since it's a recycle
|
|
203
|
+
_skipBuildLog: true,
|
|
204
|
+
},
|
|
205
|
+
shouldPrintDebug: false,
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
await newPool.run(warmupTask, { name: 'runTask' })
|
|
209
|
+
|
|
210
|
+
// destroy old pool - pending tasks will be rejected
|
|
211
|
+
oldPool.removeAllListeners()
|
|
212
|
+
oldPool.destroy().catch(() => {})
|
|
213
|
+
|
|
214
|
+
// restore stderr/stdout after a delay
|
|
215
|
+
setTimeout(() => {
|
|
216
|
+
process.stderr.write = originalStderr
|
|
217
|
+
process.stdout.write = originalStdout
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
console.log(` ♻️ [hanzo-gui] recycled worker pool (${Date.now() - start}ms)`)
|
|
221
|
+
} finally {
|
|
222
|
+
setRecycling(false)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Load Hanzo GUI build configuration asynchronously
|
|
228
|
+
* Uses esbuild-wasm to avoid EPIPE errors from native esbuild service lifecycle
|
|
229
|
+
*/
|
|
230
|
+
export async function loadGuiBuildConfig(
|
|
231
|
+
guiOptions: Partial<GuiOptions> | undefined
|
|
232
|
+
): Promise<GuiOptions> {
|
|
233
|
+
const { default: Static } = await import('@hanzogui/static')
|
|
234
|
+
|
|
235
|
+
return Static.loadGuiBuildConfigAsync(guiOptions)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Extract Hanzo GUI components to className-based CSS for web
|
|
240
|
+
*/
|
|
241
|
+
export async function extractToClassNames(params: {
|
|
242
|
+
source: string | Buffer
|
|
243
|
+
sourcePath?: string
|
|
244
|
+
options: GuiOptions
|
|
245
|
+
shouldPrintDebug?: boolean | 'verbose'
|
|
246
|
+
}): Promise<any> {
|
|
247
|
+
const { source, sourcePath = '', options, shouldPrintDebug = false } = params
|
|
248
|
+
|
|
249
|
+
if (typeof source !== 'string') {
|
|
250
|
+
throw new Error('`source` must be a string of javascript')
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const task = {
|
|
254
|
+
type: 'extractToClassNames',
|
|
255
|
+
source,
|
|
256
|
+
sourcePath,
|
|
257
|
+
options,
|
|
258
|
+
shouldPrintDebug,
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const pool = getPool()
|
|
262
|
+
const result = (await pool.run(task, { name: 'runTask' })) as any
|
|
263
|
+
|
|
264
|
+
if (!result.success) {
|
|
265
|
+
const errorMessage = [
|
|
266
|
+
`[gui-extract] Error processing file: ${sourcePath || '(unknown)'}`,
|
|
267
|
+
``,
|
|
268
|
+
result.error,
|
|
269
|
+
result.stack ? `\n${result.stack}` : '',
|
|
270
|
+
]
|
|
271
|
+
.filter(Boolean)
|
|
272
|
+
.join('\n')
|
|
273
|
+
|
|
274
|
+
throw new Error(errorMessage)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// check if we need to recycle the worker to prevent RSS bloat
|
|
278
|
+
const count = incrementTaskCount()
|
|
279
|
+
if (count >= MAX_TASKS_BEFORE_RECYCLE) {
|
|
280
|
+
resetTaskCount()
|
|
281
|
+
// recycle asynchronously with hot-swap to not block current request
|
|
282
|
+
recyclePool(options).catch(() => {})
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return result.data
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Extract Hanzo GUI components to React Native StyleSheet format
|
|
290
|
+
*/
|
|
291
|
+
export async function extractToNative(
|
|
292
|
+
sourceFileName: string,
|
|
293
|
+
sourceCode: string,
|
|
294
|
+
options: GuiOptions
|
|
295
|
+
): Promise<any> {
|
|
296
|
+
const task = {
|
|
297
|
+
type: 'extractToNative',
|
|
298
|
+
sourceFileName,
|
|
299
|
+
sourceCode,
|
|
300
|
+
options,
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const pool = getPool()
|
|
304
|
+
const result = (await pool.run(task, { name: 'runTask' })) as any
|
|
305
|
+
|
|
306
|
+
if (!result.success) {
|
|
307
|
+
const errorMessage = [
|
|
308
|
+
`[gui-extract] Error processing file: ${sourceFileName || '(unknown)'}`,
|
|
309
|
+
``,
|
|
310
|
+
result.error,
|
|
311
|
+
result.stack ? `\n${result.stack}` : '',
|
|
312
|
+
]
|
|
313
|
+
.filter(Boolean)
|
|
314
|
+
.join('\n')
|
|
315
|
+
|
|
316
|
+
throw new Error(errorMessage)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// check if we need to recycle the worker to prevent RSS bloat
|
|
320
|
+
const count = incrementTaskCount()
|
|
321
|
+
if (count >= MAX_TASKS_BEFORE_RECYCLE) {
|
|
322
|
+
resetTaskCount()
|
|
323
|
+
// recycle asynchronously with hot-swap to not block current request
|
|
324
|
+
recyclePool(options).catch(() => {})
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return result.data
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Watch Hanzo GUI config for changes and reload when it changes
|
|
332
|
+
*/
|
|
333
|
+
export async function watchGuiConfig(
|
|
334
|
+
options: GuiOptions
|
|
335
|
+
): Promise<{ dispose: () => void } | undefined> {
|
|
336
|
+
// For now, we'll use the static package's watcher directly
|
|
337
|
+
// This could be improved to use worker-based watching
|
|
338
|
+
const { default: Static } = await import('@hanzogui/static')
|
|
339
|
+
const watcher = await Static.watchGuiConfig(options)
|
|
340
|
+
|
|
341
|
+
if (!watcher) {
|
|
342
|
+
return
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Wrap the dispose to also clear worker cache
|
|
346
|
+
const originalDispose = watcher.dispose
|
|
347
|
+
return {
|
|
348
|
+
dispose: () => {
|
|
349
|
+
originalDispose()
|
|
350
|
+
if (getSharedPool()) {
|
|
351
|
+
// Fire and forget - errors are handled internally
|
|
352
|
+
clearWorkerCache()
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Clear the worker's config cache
|
|
360
|
+
* Call this when config files change
|
|
361
|
+
*/
|
|
362
|
+
export async function clearWorkerCache(): Promise<void> {
|
|
363
|
+
const pool = getSharedPool()
|
|
364
|
+
if (!pool || isClosing()) return
|
|
365
|
+
|
|
366
|
+
const task = { type: 'clearCache' }
|
|
367
|
+
await pool.run(task, { name: 'runTask' })
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Clean up the worker pool on exit
|
|
372
|
+
* Should be called when the build process completes
|
|
373
|
+
*/
|
|
374
|
+
export async function destroyPool(): Promise<void> {
|
|
375
|
+
const pool = getSharedPool()
|
|
376
|
+
if (pool) {
|
|
377
|
+
setClosing(true)
|
|
378
|
+
try {
|
|
379
|
+
await pool.close()
|
|
380
|
+
} finally {
|
|
381
|
+
setSharedPool(null)
|
|
382
|
+
setClosing(false)
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Get pool statistics for debugging
|
|
389
|
+
*/
|
|
390
|
+
export function getPoolStats() {
|
|
391
|
+
const pool = getSharedPool()
|
|
392
|
+
if (!pool) {
|
|
393
|
+
return null
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
threads: pool.threads.length,
|
|
397
|
+
queueSize: pool.queueSize,
|
|
398
|
+
completed: pool.completed,
|
|
399
|
+
duration: pool.duration,
|
|
400
|
+
utilization: pool.utilization,
|
|
401
|
+
}
|
|
402
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hanzogui/static-worker
|
|
3
|
+
*
|
|
4
|
+
* Pure worker-based API for Hanzo GUI static extraction.
|
|
5
|
+
* All operations run in a worker thread for better performance and isolation.
|
|
6
|
+
*
|
|
7
|
+
* This package provides a clean async API that wraps @hanzogui/static's worker
|
|
8
|
+
* implementation without exposing any sync/legacy APIs.
|
|
9
|
+
*/
|
|
10
|
+
import type { GuiOptions } from '@hanzogui/types';
|
|
11
|
+
export type { ExtractedResponse, GuiProjectInfo } from '@hanzogui/static';
|
|
12
|
+
export type { GuiOptions } from '@hanzogui/types';
|
|
13
|
+
export declare const getPragmaOptions: (props: {
|
|
14
|
+
source: string;
|
|
15
|
+
path: string;
|
|
16
|
+
}) => Promise<{
|
|
17
|
+
shouldPrintDebug: boolean | "verbose";
|
|
18
|
+
shouldDisable: boolean;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Load Hanzo GUI configuration in worker
|
|
22
|
+
* Sends a warmup task to trigger config loading
|
|
23
|
+
* bundleConfig auto-detects if files exist and skips rebuild
|
|
24
|
+
*/
|
|
25
|
+
export declare function loadGui(options: Partial<GuiOptions>): Promise<any>;
|
|
26
|
+
/**
|
|
27
|
+
* Load Hanzo GUI build configuration asynchronously
|
|
28
|
+
* Uses esbuild-wasm to avoid EPIPE errors from native esbuild service lifecycle
|
|
29
|
+
*/
|
|
30
|
+
export declare function loadGuiBuildConfig(guiOptions: Partial<GuiOptions> | undefined): Promise<GuiOptions>;
|
|
31
|
+
/**
|
|
32
|
+
* Extract Hanzo GUI components to className-based CSS for web
|
|
33
|
+
*/
|
|
34
|
+
export declare function extractToClassNames(params: {
|
|
35
|
+
source: string | Buffer;
|
|
36
|
+
sourcePath?: string;
|
|
37
|
+
options: GuiOptions;
|
|
38
|
+
shouldPrintDebug?: boolean | 'verbose';
|
|
39
|
+
}): Promise<any>;
|
|
40
|
+
/**
|
|
41
|
+
* Extract Hanzo GUI components to React Native StyleSheet format
|
|
42
|
+
*/
|
|
43
|
+
export declare function extractToNative(sourceFileName: string, sourceCode: string, options: GuiOptions): Promise<any>;
|
|
44
|
+
/**
|
|
45
|
+
* Watch Hanzo GUI config for changes and reload when it changes
|
|
46
|
+
*/
|
|
47
|
+
export declare function watchGuiConfig(options: GuiOptions): Promise<{
|
|
48
|
+
dispose: () => void;
|
|
49
|
+
} | undefined>;
|
|
50
|
+
/**
|
|
51
|
+
* Clear the worker's config cache
|
|
52
|
+
* Call this when config files change
|
|
53
|
+
*/
|
|
54
|
+
export declare function clearWorkerCache(): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Clean up the worker pool on exit
|
|
57
|
+
* Should be called when the build process completes
|
|
58
|
+
*/
|
|
59
|
+
export declare function destroyPool(): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Get pool statistics for debugging
|
|
62
|
+
*/
|
|
63
|
+
export declare function getPoolStats(): {
|
|
64
|
+
threads: number;
|
|
65
|
+
queueSize: number;
|
|
66
|
+
completed: number;
|
|
67
|
+
duration: number;
|
|
68
|
+
utilization: number;
|
|
69
|
+
} | null;
|
|
70
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAIjD,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACzE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,eAAO,MAAM,gBAAgB,GAAU,OAAO;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;;;EAG7E,CAAA;AA2GD;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAuBxE;AAsED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,SAAS,GAC1C,OAAO,CAAC,UAAU,CAAC,CAIrB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,UAAU,CAAA;IACnB,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CACvC,GAAG,OAAO,CAAC,GAAG,CAAC,CAwCf;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,GAAG,CAAC,CAiCd;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,GAAG,SAAS,CAAC,CAqB9C;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMtD;AAED;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAWjD;AAED;;GAEG;AACH,wBAAgB,YAAY;;;;;;SAY3B"}
|