@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.
@@ -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
+ }
@@ -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"}