tailwind-styled-v4 5.0.8 → 5.0.10

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.
Files changed (140) hide show
  1. package/CHANGELOG.md +204 -416
  2. package/README.md +45 -15
  3. package/dist/{analyzeWorkspace-DuJKh7Ty.d.mts → analyzeWorkspace-BS5O4rhC.d.mts} +47 -2
  4. package/dist/{analyzeWorkspace-Ct_NTAWt.d.ts → analyzeWorkspace-DDOQdzzI.d.ts} +47 -2
  5. package/dist/analyzer.d.mts +5 -3
  6. package/dist/analyzer.d.ts +5 -3
  7. package/dist/analyzer.js +563 -468
  8. package/dist/analyzer.js.map +1 -1
  9. package/dist/analyzer.mjs +562 -467
  10. package/dist/analyzer.mjs.map +1 -1
  11. package/dist/animate.d.mts +4 -7
  12. package/dist/animate.d.ts +4 -7
  13. package/dist/animate.js +171 -265
  14. package/dist/animate.js.map +1 -1
  15. package/dist/animate.mjs +165 -264
  16. package/dist/animate.mjs.map +1 -1
  17. package/dist/atomic.d.mts +22 -1
  18. package/dist/atomic.d.ts +22 -1
  19. package/dist/atomic.js +221 -165
  20. package/dist/atomic.js.map +1 -1
  21. package/dist/atomic.mjs +200 -165
  22. package/dist/atomic.mjs.map +1 -1
  23. package/dist/cli.d.mts +60 -1
  24. package/dist/cli.d.ts +60 -1
  25. package/dist/cli.js +1261 -1517
  26. package/dist/cli.js.map +1 -1
  27. package/dist/cli.mjs +1238 -1513
  28. package/dist/cli.mjs.map +1 -1
  29. package/dist/compiler.d.mts +38 -7
  30. package/dist/compiler.d.ts +38 -7
  31. package/dist/compiler.js +174 -197
  32. package/dist/compiler.js.map +1 -1
  33. package/dist/compiler.mjs +151 -194
  34. package/dist/compiler.mjs.map +1 -1
  35. package/dist/devtools.js +7 -31
  36. package/dist/devtools.js.map +1 -1
  37. package/dist/devtools.mjs +7 -31
  38. package/dist/devtools.mjs.map +1 -1
  39. package/dist/engine.d.mts +134 -63
  40. package/dist/engine.d.ts +134 -63
  41. package/dist/engine.js +2863 -2482
  42. package/dist/engine.js.map +1 -1
  43. package/dist/engine.mjs +2852 -2485
  44. package/dist/engine.mjs.map +1 -1
  45. package/dist/{index-eWAocnD2.d.mts → index-NDINUhLN.d.mts} +3 -1
  46. package/dist/{index-eWAocnD2.d.ts → index-NDINUhLN.d.ts} +3 -1
  47. package/dist/index.d.mts +63 -32
  48. package/dist/index.d.ts +63 -32
  49. package/dist/index.js +335 -169
  50. package/dist/index.js.map +1 -1
  51. package/dist/index.mjs +315 -169
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/{liveTokenEngine-DSUk88P6.d.ts → liveTokenEngine-CN9ian1R.d.ts} +1 -1
  54. package/dist/{liveTokenEngine-CX5_0c4q.d.mts → liveTokenEngine-DKoWRtqH.d.mts} +1 -1
  55. package/dist/next.d.mts +10 -4
  56. package/dist/next.d.ts +10 -4
  57. package/dist/next.js +32 -45
  58. package/dist/next.js.map +1 -1
  59. package/dist/next.mjs +30 -43
  60. package/dist/next.mjs.map +1 -1
  61. package/dist/plugin-api.d.mts +8 -2
  62. package/dist/plugin-api.d.ts +8 -2
  63. package/dist/plugin-api.js +14 -2
  64. package/dist/plugin-api.js.map +1 -1
  65. package/dist/plugin-api.mjs +14 -3
  66. package/dist/plugin-api.mjs.map +1 -1
  67. package/dist/plugin-registry.js +51 -11
  68. package/dist/plugin-registry.js.map +1 -1
  69. package/dist/plugin-registry.mjs +51 -11
  70. package/dist/plugin-registry.mjs.map +1 -1
  71. package/dist/plugin.d.mts +5 -7
  72. package/dist/plugin.d.ts +5 -7
  73. package/dist/plugin.js +16 -15
  74. package/dist/plugin.js.map +1 -1
  75. package/dist/plugin.mjs +16 -16
  76. package/dist/plugin.mjs.map +1 -1
  77. package/dist/rspack.js +17 -38
  78. package/dist/rspack.js.map +1 -1
  79. package/dist/rspack.mjs +15 -36
  80. package/dist/rspack.mjs.map +1 -1
  81. package/dist/runtime.d.mts +2 -2
  82. package/dist/runtime.d.ts +2 -2
  83. package/dist/scanner.d.mts +10 -1
  84. package/dist/scanner.d.ts +10 -1
  85. package/dist/scanner.js +298 -124
  86. package/dist/scanner.js.map +1 -1
  87. package/dist/scanner.mjs +296 -124
  88. package/dist/scanner.mjs.map +1 -1
  89. package/dist/shared.d.mts +1 -1
  90. package/dist/shared.d.ts +1 -1
  91. package/dist/shared.js +104 -176
  92. package/dist/shared.js.map +1 -1
  93. package/dist/shared.mjs +85 -176
  94. package/dist/shared.mjs.map +1 -1
  95. package/dist/storybook-addon.d.mts +1 -1
  96. package/dist/storybook-addon.d.ts +1 -1
  97. package/dist/svelte.d.mts +1 -1
  98. package/dist/svelte.d.ts +1 -1
  99. package/dist/svelte.js +166 -3
  100. package/dist/svelte.js.map +1 -1
  101. package/dist/svelte.mjs +143 -1
  102. package/dist/svelte.mjs.map +1 -1
  103. package/dist/syntax.js +21 -21
  104. package/dist/syntax.js.map +1 -1
  105. package/dist/syntax.mjs +21 -21
  106. package/dist/syntax.mjs.map +1 -1
  107. package/dist/testing.js +9 -1
  108. package/dist/testing.js.map +1 -1
  109. package/dist/testing.mjs +9 -1
  110. package/dist/testing.mjs.map +1 -1
  111. package/dist/theme.d.mts +2 -2
  112. package/dist/theme.d.ts +2 -2
  113. package/dist/theme.js +40 -112
  114. package/dist/theme.js.map +1 -1
  115. package/dist/theme.mjs +37 -110
  116. package/dist/theme.mjs.map +1 -1
  117. package/dist/turbopackLoader.js +84 -126
  118. package/dist/turbopackLoader.js.map +1 -1
  119. package/dist/turbopackLoader.mjs +68 -124
  120. package/dist/turbopackLoader.mjs.map +1 -1
  121. package/dist/tw.js +1256 -1517
  122. package/dist/tw.js.map +1 -1
  123. package/dist/tw.mjs +1236 -1513
  124. package/dist/tw.mjs.map +1 -1
  125. package/dist/vite.js +1783 -823
  126. package/dist/vite.js.map +1 -1
  127. package/dist/vite.mjs +1767 -821
  128. package/dist/vite.mjs.map +1 -1
  129. package/dist/vue.d.mts +1 -1
  130. package/dist/vue.d.ts +1 -1
  131. package/dist/vue.js +165 -4
  132. package/dist/vue.js.map +1 -1
  133. package/dist/vue.mjs +141 -1
  134. package/dist/vue.mjs.map +1 -1
  135. package/dist/webpackLoader.js +69 -108
  136. package/dist/webpackLoader.js.map +1 -1
  137. package/dist/webpackLoader.mjs +49 -104
  138. package/dist/webpackLoader.mjs.map +1 -1
  139. package/native/tailwind-styled-native.node +0 -0
  140. package/package.json +22 -24
package/dist/vite.mjs CHANGED
@@ -1,9 +1,13 @@
1
+ import { z } from 'zod';
1
2
  import { createRequire } from 'module';
2
- import path3 from 'path';
3
+ import * as fs4 from 'fs';
4
+ import fs4__default from 'fs';
5
+ import * as path6 from 'path';
6
+ import path6__default from 'path';
7
+ import { createHash } from 'crypto';
3
8
  import { fileURLToPath, pathToFileURL } from 'url';
4
- import fs from 'fs';
5
- import { Worker } from 'worker_threads';
6
- import { z } from 'zod';
9
+ import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';
10
+ import { availableParallelism } from 'os';
7
11
  import 'perf_hooks';
8
12
 
9
13
  /* tailwind-styled-v4 v5.0.4 | MIT | https://github.com/dictionar32/tailwind-styled-v4 */
@@ -34,6 +38,260 @@ var __copyProps = (to, from, except, desc) => {
34
38
  };
35
39
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
40
 
41
+ // packages/domain/shared/src/trace.ts
42
+ function getHealthColor(status) {
43
+ switch (status) {
44
+ case "healthy":
45
+ return "#34d399";
46
+ case "degraded":
47
+ return "#fbbf24";
48
+ case "unhealthy":
49
+ return "#f87171";
50
+ default:
51
+ return "#52525b";
52
+ }
53
+ }
54
+ function getModeColor(mode) {
55
+ switch (mode) {
56
+ case "build":
57
+ return "#fbbf24";
58
+ case "watch":
59
+ return "#34d399";
60
+ case "jit":
61
+ return "#60a5fa";
62
+ case "error":
63
+ return "#f87171";
64
+ case "idle":
65
+ return "#71717a";
66
+ default:
67
+ return "#52525b";
68
+ }
69
+ }
70
+ function formatMemory(bytes) {
71
+ if (bytes < 1024) return `${Math.round(bytes)}B`;
72
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
73
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
74
+ }
75
+ function formatDuration(ms) {
76
+ if (ms === null) return "\u2014";
77
+ if (ms < 1e3) return `${ms}ms`;
78
+ return `${(ms / 1e3).toFixed(1)}s`;
79
+ }
80
+ function calculateHealth(metrics, summary) {
81
+ if (summary?.health?.status) return summary.health.status;
82
+ if (metrics.mode === "error") return "unhealthy";
83
+ if ((metrics.buildMs ?? 0) > 5e3) return "degraded";
84
+ if (metrics.memoryMb && metrics.memoryMb.heapUsed > 500) return "degraded";
85
+ return "healthy";
86
+ }
87
+ function getBuildTimeColor(ms) {
88
+ if (ms === null) return "#52525b";
89
+ if (ms > 1e3) return "#f87171";
90
+ if (ms > 500) return "#fbbf24";
91
+ return "#34d399";
92
+ }
93
+ function getMemoryColor(mb) {
94
+ if (mb > 500) return "#f87171";
95
+ if (mb > 250) return "#fbbf24";
96
+ return "#34d399";
97
+ }
98
+ function createTraceSnapshot(data) {
99
+ return {
100
+ generatedAt: data.generatedAt || (/* @__PURE__ */ new Date()).toISOString(),
101
+ buildMs: data.buildMs ?? null,
102
+ scanMs: data.scanMs ?? null,
103
+ analyzeMs: data.analyzeMs ?? null,
104
+ compileMs: data.compileMs ?? null,
105
+ memoryMb: data.memoryMb ?? null,
106
+ classCount: data.classCount ?? null,
107
+ fileCount: data.fileCount ?? null,
108
+ cssBytes: data.cssBytes ?? null,
109
+ mode: data.mode ?? null,
110
+ eventsReceived: data.eventsReceived ?? void 0,
111
+ eventsProcessed: data.eventsProcessed ?? void 0,
112
+ batchesProcessed: data.batchesProcessed ?? void 0,
113
+ incrementalUpdates: data.incrementalUpdates ?? void 0,
114
+ fullRescans: data.fullRescans ?? void 0
115
+ };
116
+ }
117
+ function getPipelinePercentages(metrics) {
118
+ const scan = metrics.scanMs ?? 0;
119
+ const analyze = metrics.analyzeMs ?? 0;
120
+ const compile = metrics.compileMs ?? 0;
121
+ const total = scan + analyze + compile;
122
+ if (total === 0) {
123
+ return { scanPct: 0, analyzePct: 0, compilePct: 0 };
124
+ }
125
+ return {
126
+ scanPct: scan / total * 100,
127
+ analyzePct: analyze / total * 100,
128
+ compilePct: compile / total * 100
129
+ };
130
+ }
131
+ var init_trace = __esm({
132
+ "packages/domain/shared/src/trace.ts"() {
133
+ }
134
+ });
135
+
136
+ // packages/domain/shared/src/error-codes.ts
137
+ function getSuggestion(code) {
138
+ return ERROR_SUGGESTIONS[code];
139
+ }
140
+ function formatErrorCode(code) {
141
+ const prefix = code.startsWith("E") ? "Error" : code.startsWith("W") ? "Warning" : "Code";
142
+ return `[${prefix} ${code}]`;
143
+ }
144
+ var ERROR_CODES, ERROR_SUGGESTIONS;
145
+ var init_error_codes = __esm({
146
+ "packages/domain/shared/src/error-codes.ts"() {
147
+ ERROR_CODES = {
148
+ // E0xx — Native binding
149
+ NATIVE_NOT_FOUND: "E001",
150
+ NATIVE_LOAD_FAILED: "E002",
151
+ NATIVE_VERSION_MISMATCH: "E003",
152
+ SCANNER_NATIVE_NOT_FOUND: "E004",
153
+ SCANNER_HASH_FAILED: "E005",
154
+ NATIVE_TRANSFORM_UNAVAILABLE: "E006",
155
+ // E2xx — Compilation
156
+ MISSING_REACT_IMPORT: "E201",
157
+ UNSUPPORTED_PATTERN: "E202",
158
+ TEMPLATE_PARSE_ERROR: "E203",
159
+ COMPILE_TIMEOUT: "E204",
160
+ // E3xx — Compatibility
161
+ TAILWIND_VERSION_UNSUPPORTED: "E301",
162
+ NODE_VERSION_UNSUPPORTED: "E302",
163
+ // E4xx — Cache
164
+ CACHE_READ_FAILED: "E401",
165
+ CACHE_WRITE_FAILED: "E402",
166
+ CACHE_CORRUPTED: "E403",
167
+ // E5xx — RSC
168
+ RSC_BOUNDARY_CONFLICT: "E501",
169
+ // W1xx — Warnings
170
+ DYNAMIC_CONTENT: "W101",
171
+ INVALID_VARIANT_VALUE: "W201",
172
+ DEPRECATED_MODE: "W301"
173
+ };
174
+ ERROR_SUGGESTIONS = {
175
+ E001: "Run: npm install @tailwind-styled/native-{platform} or build from source",
176
+ E002: "Try: npm rebuild or reinstall the package",
177
+ E003: "Run: npm install tailwind-styled-v4@latest to sync versions",
178
+ E004: "Run: npm install @tailwind-styled/scanner",
179
+ E006: "Run: npm install @tailwind-styled/compiler",
180
+ E301: "Upgrade: npm install tailwindcss@^4"
181
+ };
182
+ }
183
+ });
184
+
185
+ // packages/domain/shared/src/compatibility.ts
186
+ function detectTailwind() {
187
+ try {
188
+ const pkgPath = __require.resolve("tailwindcss/package.json");
189
+ const { version } = __require(pkgPath);
190
+ const major = Number.parseInt(version.split(".")[0], 10);
191
+ return { version, major, supported: major >= 4, path: pkgPath };
192
+ } catch {
193
+ return { version: "not-installed", major: 0, supported: false, path: null };
194
+ }
195
+ }
196
+ function assertTailwindV4() {
197
+ const info = detectTailwind();
198
+ if (!info.supported) {
199
+ const message = info.major === 0 ? "tailwindcss is not installed. Run: npm install tailwindcss@^4" : `tailwind-styled-v4 requires Tailwind CSS v4.x. Found: v${info.version}. Upgrade: npm install tailwindcss@^4`;
200
+ if (process.env.NODE_ENV !== "production") {
201
+ console.warn(`[tailwind-styled] ${message}`);
202
+ }
203
+ }
204
+ }
205
+ function getTailwindVersion() {
206
+ return detectTailwind().version;
207
+ }
208
+ function isTailwindV4() {
209
+ return detectTailwind().supported;
210
+ }
211
+ var init_compatibility = __esm({
212
+ "packages/domain/shared/src/compatibility.ts"() {
213
+ }
214
+ });
215
+ function safeParseNative(schema, data, fallback) {
216
+ const result = schema.safeParse(data);
217
+ return result.success ? result.data : fallback;
218
+ }
219
+ function parseNative(schema, data, context) {
220
+ const result = schema.safeParse(data);
221
+ if (!result.success) {
222
+ const first = result.error.issues[0];
223
+ const path13 = first?.path?.join(".") ?? "(root)";
224
+ throw new Error(
225
+ `[${context}] Native binding returned unexpected data: ${path13}: ${first?.message ?? "validation failed"}`
226
+ );
227
+ }
228
+ return result.data;
229
+ }
230
+ var NativeScanFileSchema, NativeScanResultSchema, NativeClassUsageSchema, NativeAnalyzerReportSchema, NativeTransformResultSchema, NativeCssCompileResultSchema, NativeWatchResultSchema, NativeCacheEntrySchema, NativeCacheReadResultSchema;
231
+ var init_native_schemas = __esm({
232
+ "packages/domain/shared/src/native-schemas.ts"() {
233
+ NativeScanFileSchema = z.object({
234
+ file: z.string().min(1, "file path cannot be empty"),
235
+ classes: z.array(z.string()),
236
+ hash: z.string().optional()
237
+ });
238
+ NativeScanResultSchema = z.object({
239
+ files: z.array(NativeScanFileSchema),
240
+ totalFiles: z.number().int().nonnegative(),
241
+ uniqueClasses: z.array(z.string())
242
+ });
243
+ NativeClassUsageSchema = z.object({
244
+ name: z.string(),
245
+ count: z.number().int().nonnegative(),
246
+ files: z.array(z.string()).optional()
247
+ });
248
+ NativeAnalyzerReportSchema = z.object({
249
+ root: z.string(),
250
+ topClasses: z.array(NativeClassUsageSchema).optional(),
251
+ safelist: z.array(z.string()).optional(),
252
+ css: z.string().optional(),
253
+ conflicts: z.array(z.unknown()).optional(),
254
+ unusedClasses: z.array(z.string()).optional(),
255
+ durationMs: z.number().nonnegative().optional()
256
+ });
257
+ NativeTransformResultSchema = z.object({
258
+ code: z.string(),
259
+ classes: z.array(z.string()),
260
+ changed: z.boolean(),
261
+ rsc: z.object({
262
+ isServer: z.boolean(),
263
+ needsClientDirective: z.boolean(),
264
+ clientReasons: z.array(z.string())
265
+ }).optional()
266
+ });
267
+ NativeCssCompileResultSchema = z.object({
268
+ css: z.string(),
269
+ resolvedClasses: z.array(z.string()),
270
+ unresolvedClasses: z.array(z.string()).optional()
271
+ });
272
+ z.object({
273
+ type: z.enum(["change", "unlink", "create"]),
274
+ path: z.string()
275
+ });
276
+ NativeWatchResultSchema = z.object({
277
+ status: z.enum(["ok", "error"]),
278
+ handleId: z.string().optional(),
279
+ error: z.string().optional()
280
+ });
281
+ NativeCacheEntrySchema = z.object({
282
+ file: z.string(),
283
+ hash: z.string(),
284
+ classes: z.array(z.string()),
285
+ timestamp: z.number(),
286
+ size: z.number().optional()
287
+ });
288
+ NativeCacheReadResultSchema = z.object({
289
+ entries: z.array(NativeCacheEntrySchema),
290
+ version: z.string().optional()
291
+ });
292
+ }
293
+ });
294
+
37
295
  // packages/domain/shared/src/esmHelpers.ts
38
296
  function getNodeModuleRef() {
39
297
  if (isBrowser) return null;
@@ -61,88 +319,551 @@ function getNodeUrl() {
61
319
  if (!_nodeUrl) _nodeUrl = nodeRequire.createRequire(import.meta.url)("node:url");
62
320
  return _nodeUrl;
63
321
  }
322
+ function getNodeFs() {
323
+ if (isBrowser) throw new Error("node:fs not available in browser");
324
+ const nodeRequire = getNodeModuleRef();
325
+ if (!nodeRequire) throw new Error("require not available");
326
+ if (!_nodeFs) _nodeFs = nodeRequire.createRequire(import.meta.url)("node:fs");
327
+ return _nodeFs;
328
+ }
329
+ function createEsmRequire(importMetaUrl) {
330
+ if (isBrowser) throw new Error("require not available in browser");
331
+ const nodeRequire = getNodeModuleRef();
332
+ if (!nodeRequire) throw new Error("require not available");
333
+ return nodeRequire.createRequire(importMetaUrl);
334
+ }
64
335
  function getDirname(importMetaUrl) {
65
336
  if (isBrowser) return "";
66
337
  const nodePath = getNodePath();
67
338
  const nodeUrl = getNodeUrl();
68
339
  return nodePath.dirname(nodeUrl.fileURLToPath(importMetaUrl));
69
340
  }
70
- var isBrowser, nodeModuleRef, _nodePath, _nodeUrl;
341
+ function getFilename(importMetaUrl) {
342
+ if (isBrowser) return "";
343
+ return getNodeUrl().fileURLToPath(importMetaUrl);
344
+ }
345
+ function resolveFromRoot(...segments) {
346
+ if (isBrowser) return segments.join("/");
347
+ const nodePath = getNodePath();
348
+ const nodeFs = getNodeFs();
349
+ let dir = getDirname(import.meta.url);
350
+ for (let i = 0; i < 10; i++) {
351
+ const pkgPath = nodePath.join(dir, "package.json");
352
+ try {
353
+ const pkg = JSON.parse(nodeFs.readFileSync(pkgPath, "utf-8"));
354
+ if (pkg.workspaces) {
355
+ return nodePath.resolve(dir, ...segments);
356
+ }
357
+ } catch {
358
+ }
359
+ dir = nodePath.dirname(dir);
360
+ }
361
+ return nodePath.resolve(process.cwd(), ...segments);
362
+ }
363
+ function tryRequire(moduleName, importMetaUrl) {
364
+ if (isBrowser) return null;
365
+ try {
366
+ return createEsmRequire(importMetaUrl)(moduleName);
367
+ } catch {
368
+ }
369
+ return null;
370
+ }
371
+ function resolveNativeNodePath(importMetaUrl, ...relativeSegments) {
372
+ if (isBrowser) return relativeSegments.join("/");
373
+ return getNodePath().resolve(getDirname(importMetaUrl), ...relativeSegments);
374
+ }
375
+ var isBrowser, nodeModuleRef, _nodePath, _nodeUrl, _nodeFs;
71
376
  var init_esmHelpers = __esm({
72
377
  "packages/domain/shared/src/esmHelpers.ts"() {
73
378
  isBrowser = typeof window !== "undefined" || typeof document !== "undefined";
74
379
  nodeModuleRef = null;
75
380
  _nodePath = null;
76
381
  _nodeUrl = null;
382
+ _nodeFs = null;
77
383
  }
78
384
  });
79
385
 
80
- // packages/domain/shared/src/native-resolution.ts
81
- function getNodeModuleRef2() {
82
- if (isBrowser2) return null;
83
- if (nodeModuleRef2 !== null) return nodeModuleRef2;
386
+ // packages/domain/shared/src/telemetry.ts
387
+ function getGlobalTelemetry() {
388
+ if (!_globalCollector) {
389
+ _globalCollector = new TelemetryCollector();
390
+ }
391
+ return _globalCollector;
392
+ }
393
+ function resetGlobalTelemetry() {
394
+ _globalCollector = null;
395
+ }
396
+ function createBuildTimer() {
397
+ const start = Date.now();
398
+ const phases = {};
399
+ let phaseStart = start;
400
+ return {
401
+ phase(name) {
402
+ const now = Date.now();
403
+ phases[name] = now - phaseStart;
404
+ phaseStart = now;
405
+ },
406
+ finish(opts) {
407
+ const now = Date.now();
408
+ const record = {
409
+ timestamp: start,
410
+ durationMs: now - start,
411
+ phases: {
412
+ scan: phases.scan ?? 0,
413
+ compile: phases.compile ?? 0,
414
+ engine: phases.engine ?? 0,
415
+ output: phases.output ?? now - start
416
+ },
417
+ cacheHitRate: opts.cacheHitRate ?? 0,
418
+ ...opts
419
+ };
420
+ getGlobalTelemetry().record(record);
421
+ return record;
422
+ }
423
+ };
424
+ }
425
+ var RING_BUFFER_SIZE, TelemetryCollector, _globalCollector;
426
+ var init_telemetry = __esm({
427
+ "packages/domain/shared/src/telemetry.ts"() {
428
+ RING_BUFFER_SIZE = 100;
429
+ TelemetryCollector = class {
430
+ data = [];
431
+ enabled;
432
+ constructor(enabled) {
433
+ this.enabled = enabled ?? (process.env.TWS_TELEMETRY === "1" || process.env.TWS_TELEMETRY === "true");
434
+ }
435
+ record(build) {
436
+ if (!this.enabled) return;
437
+ if (this.data.length >= RING_BUFFER_SIZE) {
438
+ this.data.shift();
439
+ }
440
+ this.data.push(build);
441
+ }
442
+ snapshot() {
443
+ return [...this.data];
444
+ }
445
+ summary() {
446
+ if (this.data.length === 0) return null;
447
+ const durations = this.data.map((d) => d.durationMs).sort((a, b) => a - b);
448
+ const p95Idx = Math.floor(durations.length * 0.95);
449
+ const avg = (arr) => arr.reduce((a, b) => a + b, 0) / arr.length;
450
+ return {
451
+ totalBuilds: this.data.length,
452
+ avgDurationMs: avg(durations),
453
+ p95DurationMs: durations[p95Idx] ?? durations[durations.length - 1] ?? 0,
454
+ avgCacheHitRate: avg(this.data.map((d) => d.cacheHitRate)),
455
+ avgFilesScanned: avg(this.data.map((d) => d.filesScanned)),
456
+ avgClassesExtracted: avg(this.data.map((d) => d.classesExtracted)),
457
+ phaseAvgs: {
458
+ scan: avg(this.data.map((d) => d.phases.scan)),
459
+ compile: avg(this.data.map((d) => d.phases.compile)),
460
+ engine: avg(this.data.map((d) => d.phases.engine)),
461
+ output: avg(this.data.map((d) => d.phases.output))
462
+ },
463
+ slowestBuildMs: durations[durations.length - 1] ?? 0,
464
+ fastestBuildMs: durations[0] ?? 0
465
+ };
466
+ }
467
+ reset() {
468
+ this.data = [];
469
+ }
470
+ /** Format ringkas untuk CLI output */
471
+ formatCli() {
472
+ const s = this.summary();
473
+ if (!s) return "[telemetry] no data";
474
+ return [
475
+ `[telemetry] ${s.totalBuilds} builds`,
476
+ `avg ${s.avgDurationMs.toFixed(0)}ms`,
477
+ `p95 ${s.p95DurationMs.toFixed(0)}ms`,
478
+ `cache hit ${(s.avgCacheHitRate * 100).toFixed(0)}%`,
479
+ `${s.avgFilesScanned.toFixed(0)} files`
480
+ ].join(" \xB7 ");
481
+ }
482
+ /** Export sebagai JSON untuk dashboard/prometheus */
483
+ toJSON() {
484
+ return {
485
+ summary: this.summary(),
486
+ history: this.data.slice(-20)
487
+ // last 20 builds
488
+ };
489
+ }
490
+ };
491
+ _globalCollector = null;
492
+ }
493
+ });
494
+ function parseJsonWithSchema(jsonString, schema, sourceName) {
495
+ let parsed;
84
496
  try {
85
- const test = typeof __require === "function" ? __require("module") : null;
86
- nodeModuleRef2 = test;
87
- return test;
497
+ parsed = JSON.parse(jsonString);
498
+ } catch (err) {
499
+ throw new Error(
500
+ `[${sourceName}] Invalid JSON: ${err instanceof Error ? err.message : String(err)}`
501
+ );
502
+ }
503
+ const result = schema.safeParse(parsed);
504
+ if (!result.success) {
505
+ const issues = result.error.issues.map((e) => ` ${e.path.join(".")}: ${e.message}`).join("\n");
506
+ throw new Error(`[${sourceName}] Schema validation failed:
507
+ ${issues}`);
508
+ }
509
+ return result.data;
510
+ }
511
+ function parseJsonFileWithSchema(filePath, schema) {
512
+ const { readFileSync } = __require("fs");
513
+ const { basename } = __require("path");
514
+ let content;
515
+ try {
516
+ content = readFileSync(filePath, "utf-8");
517
+ } catch (err) {
518
+ throw new Error(
519
+ `[${basename(filePath)}] Could not read file: ${err instanceof Error ? err.message : String(err)}`
520
+ );
521
+ }
522
+ return parseJsonWithSchema(content, schema, basename(filePath));
523
+ }
524
+ var ScanCacheClassEntrySchema, ScanCacheSchema, TailwindContentItemSchema, TailwindConfigSchema, RegistryPluginEntrySchema, RegistryFileSchema, PackageJsonSchema;
525
+ var init_configSchemas = __esm({
526
+ "packages/domain/shared/src/configSchemas.ts"() {
527
+ ScanCacheClassEntrySchema = z.object({
528
+ name: z.string().min(1),
529
+ usedIn: z.array(z.string()),
530
+ risk: z.enum(["low", "medium", "high"]).default("low"),
531
+ bundleContribution: z.number().nonnegative().default(0),
532
+ variants: z.array(z.string()).default([])
533
+ });
534
+ ScanCacheSchema = z.object({
535
+ version: z.string().default("1"),
536
+ generatedAt: z.string(),
537
+ root: z.string(),
538
+ classNames: z.array(ScanCacheClassEntrySchema),
539
+ totalFiles: z.number().int().nonnegative(),
540
+ uniqueCount: z.number().int().nonnegative()
541
+ });
542
+ TailwindContentItemSchema = z.union([
543
+ z.string(),
544
+ z.object({
545
+ raw: z.string(),
546
+ extension: z.string().optional()
547
+ }),
548
+ z.object({
549
+ files: z.array(z.string()),
550
+ transform: z.record(z.string(), z.unknown()).optional()
551
+ })
552
+ ]);
553
+ TailwindConfigSchema = z.object({
554
+ content: z.array(TailwindContentItemSchema).optional(),
555
+ theme: z.record(z.string(), z.unknown()).optional(),
556
+ plugins: z.array(z.unknown()).optional(),
557
+ darkMode: z.union([z.literal("class"), z.literal("media"), z.literal(false)]).optional(),
558
+ prefix: z.string().optional(),
559
+ safelist: z.array(z.union([z.string(), z.object({ pattern: z.instanceof(RegExp) })])).optional(),
560
+ blocklist: z.array(z.string()).optional()
561
+ }).passthrough();
562
+ RegistryPluginEntrySchema = z.object({
563
+ name: z.string().min(1),
564
+ description: z.string(),
565
+ version: z.string(),
566
+ tags: z.array(z.string()).default([]),
567
+ official: z.boolean().default(false),
568
+ docs: z.string().url().optional(),
569
+ install: z.string().optional(),
570
+ integrity: z.string().optional()
571
+ });
572
+ RegistryFileSchema = z.object({
573
+ version: z.string(),
574
+ official: z.array(RegistryPluginEntrySchema).default([]),
575
+ community: z.array(RegistryPluginEntrySchema).default([])
576
+ });
577
+ PackageJsonSchema = z.object({
578
+ name: z.string(),
579
+ version: z.string(),
580
+ scripts: z.record(z.string(), z.string()).optional(),
581
+ dependencies: z.record(z.string(), z.string()).optional(),
582
+ devDependencies: z.record(z.string(), z.string()).optional(),
583
+ peerDependencies: z.record(z.string(), z.string()).optional(),
584
+ main: z.string().optional(),
585
+ module: z.string().optional(),
586
+ exports: z.unknown().optional(),
587
+ type: z.enum(["module", "commonjs"]).optional()
588
+ }).passthrough();
589
+ }
590
+ });
591
+
592
+ // packages/domain/shared/src/workerResolver.ts
593
+ function getDirnameFromUrl(importMetaUrl) {
594
+ if (!importMetaUrl) return "";
595
+ if (isBrowser2) return "";
596
+ try {
597
+ const nodeUrl = __require(NODE_URL);
598
+ const nodePath = __require(NODE_PATH);
599
+ return nodePath.dirname(nodeUrl.fileURLToPath(importMetaUrl));
88
600
  } catch {
89
- nodeModuleRef2 = null;
90
- return null;
601
+ if (importMetaUrl.startsWith("file://")) {
602
+ const filePath = importMetaUrl.slice(7);
603
+ const lastSlash = filePath.lastIndexOf("/");
604
+ return lastSlash >= 0 ? filePath.slice(0, lastSlash) : filePath;
605
+ }
606
+ return "";
91
607
  }
92
608
  }
93
- function getNodeFs() {
94
- if (isBrowser2) return { existsSync: () => false };
95
- const nodeRequire = getNodeModuleRef2();
96
- if (!nodeRequire) return { existsSync: () => false };
97
- if (!_nodeFs) _nodeFs = nodeRequire.createRequire(import.meta.url)("node:fs");
98
- return _nodeFs;
609
+ function resolvePath(...segments) {
610
+ if (isBrowser2) return segments.join("/").replace(/\/+/g, "/");
611
+ try {
612
+ const nodePath = __require(NODE_PATH);
613
+ return nodePath.resolve(...segments);
614
+ } catch {
615
+ return segments.join("/").replace(/\/+/g, "/");
616
+ }
99
617
  }
100
- function getNodePath2() {
101
- if (isBrowser2) return { resolve: () => "", dirname: "" };
102
- const nodeRequire = getNodeModuleRef2();
103
- if (!nodeRequire) return { resolve: () => "", dirname: "" };
104
- if (!_nodePath2) _nodePath2 = nodeRequire.createRequire(import.meta.url)("node:path");
105
- return _nodePath2;
618
+ function existsSync(path13) {
619
+ if (isBrowser2) return false;
620
+ try {
621
+ const nodeFs = __require(NODE_FS);
622
+ return nodeFs.existsSync(path13);
623
+ } catch {
624
+ return false;
625
+ }
106
626
  }
107
- function getRequire(_importMetaUrl) {
108
- if (isBrowser2) return () => {
109
- throw new Error("node:module not available");
110
- };
111
- const nodeRequire = getNodeModuleRef2();
112
- if (!nodeRequire) return () => {
113
- throw new Error("require not available");
114
- };
115
- if (!_require) _require = nodeRequire.createRequire(_importMetaUrl);
116
- return _require;
627
+ function resolveWorkerPath(opts) {
628
+ if (isBrowser2) {
629
+ throw new Error("Worker resolution not available in browser");
630
+ }
631
+ const {
632
+ basename,
633
+ importMetaUrl,
634
+ extensions = [".cjs", ".js", ".mjs"],
635
+ subdirs = [".", "workers", "lib"],
636
+ required = true
637
+ } = opts;
638
+ const runtimeDir = getDirnameFromUrl(importMetaUrl);
639
+ for (const subdir of subdirs) {
640
+ for (const ext of extensions) {
641
+ const candidate = resolvePath(runtimeDir, subdir, `${basename}${ext}`);
642
+ if (existsSync(candidate)) {
643
+ return {
644
+ path: candidate,
645
+ extension: ext,
646
+ format: ext === ".cjs" ? "cjs" : "esm"
647
+ };
648
+ }
649
+ }
650
+ }
651
+ if (required) {
652
+ const tried = subdirs.flatMap(
653
+ (d) => extensions.map((e) => resolvePath(runtimeDir, d, `${basename}${e}`))
654
+ );
655
+ throw new Error(
656
+ `[worker-resolver] Could not find worker script "${basename}".
657
+ Tried:
658
+ ${tried.map((p) => ` - ${p}`).join("\n")}
659
+ Ensure the package is built: npm run build`
660
+ );
661
+ }
662
+ return { path: "", extension: "", format: "cjs" };
663
+ }
664
+ function resolveLoaderPath(loaderBasename, importMetaUrl) {
665
+ return resolveWorkerPath({
666
+ basename: loaderBasename,
667
+ importMetaUrl,
668
+ extensions: [".cjs", ".js", ".mjs"],
669
+ subdirs: [".", "loaders", "lib"]
670
+ }).path;
671
+ }
672
+ var isBrowser2, NODE_URL, NODE_FS, NODE_PATH;
673
+ var init_workerResolver = __esm({
674
+ "packages/domain/shared/src/workerResolver.ts"() {
675
+ isBrowser2 = typeof window !== "undefined" || typeof document !== "undefined";
676
+ NODE_URL = typeof window === "undefined" || typeof document === "undefined" ? "node:url" : null;
677
+ NODE_FS = typeof window === "undefined" || typeof document === "undefined" ? "node:fs" : null;
678
+ NODE_PATH = typeof window === "undefined" || typeof document === "undefined" ? "node:path" : null;
679
+ }
680
+ });
681
+
682
+ // packages/domain/shared/src/codegen.ts
683
+ function generateComponentCode(opts) {
684
+ const {
685
+ name,
686
+ tag = "div",
687
+ base = "",
688
+ variants = {},
689
+ defaultVariants = {},
690
+ compoundVariants = [],
691
+ framework = "react",
692
+ withTypes = true
693
+ } = opts;
694
+ const variantKeys = Object.keys(variants);
695
+ const lines = [];
696
+ if (framework === "react") {
697
+ lines.push(`import { tw } from "tailwind-styled-v4"`);
698
+ if (withTypes && variantKeys.length > 0) {
699
+ lines.push(`import type { InferVariantProps } from "tailwind-styled-v4"`);
700
+ }
701
+ } else if (framework === "vue") {
702
+ lines.push(`import { tw } from "@tailwind-styled/vue"`);
703
+ } else if (framework === "svelte") {
704
+ lines.push(`import { tw } from "@tailwind-styled/svelte"`);
705
+ }
706
+ lines.push("");
707
+ const configLines = [`export const ${name} = tw.${tag}({`];
708
+ if (base) configLines.push(` base: "${base}",`);
709
+ if (variantKeys.length > 0) {
710
+ configLines.push(` variants: {`);
711
+ for (const [key, values] of Object.entries(variants)) {
712
+ configLines.push(` ${key}: {`);
713
+ for (const [val, cls] of Object.entries(values)) {
714
+ configLines.push(` ${val}: "${cls}",`);
715
+ }
716
+ configLines.push(` },`);
717
+ }
718
+ configLines.push(` },`);
719
+ }
720
+ if (compoundVariants.length > 0) {
721
+ configLines.push(` compoundVariants: [`);
722
+ for (const cv of compoundVariants) {
723
+ const { class: cls, ...conditions } = cv;
724
+ const condStr = Object.entries(conditions).map(([k, v]) => `${k}: "${v}"`).join(", ");
725
+ configLines.push(` { ${condStr}, class: "${cls}" },`);
726
+ }
727
+ configLines.push(` ],`);
728
+ }
729
+ if (Object.keys(defaultVariants).length > 0) {
730
+ configLines.push(` defaultVariants: {`);
731
+ for (const [k, v] of Object.entries(defaultVariants)) {
732
+ configLines.push(` ${k}: "${v}",`);
733
+ }
734
+ configLines.push(` },`);
735
+ }
736
+ configLines.push(`})`);
737
+ lines.push(...configLines);
738
+ if (withTypes && variantKeys.length > 0 && framework === "react") {
739
+ lines.push("");
740
+ lines.push(`export type ${name}Props = InferVariantProps<typeof ${name}> & {`);
741
+ lines.push(` children?: React.ReactNode`);
742
+ lines.push(` className?: string`);
743
+ lines.push(`}`);
744
+ }
745
+ return lines.join("\n");
746
+ }
747
+ function generateStorybookStory(opts) {
748
+ const { name, variants = {}, defaultVariants = {} } = opts;
749
+ const lines = [];
750
+ lines.push(`import type { Meta, StoryObj } from "@storybook/react"`);
751
+ lines.push(`import { ${name} } from "./${name}"`);
752
+ lines.push(`import { generateArgTypes, generateDefaultArgs } from "tailwind-styled-v4"`);
753
+ lines.push(``);
754
+ lines.push(`const config = {`);
755
+ if (Object.keys(variants).length > 0) {
756
+ lines.push(` variants: ${JSON.stringify(variants, null, 2).replace(/^/gm, " ")},`);
757
+ }
758
+ if (Object.keys(defaultVariants).length > 0) {
759
+ lines.push(` defaultVariants: ${JSON.stringify(defaultVariants)},`);
760
+ }
761
+ lines.push(`}`);
762
+ lines.push(``);
763
+ lines.push(`const meta: Meta<typeof ${name}> = {`);
764
+ lines.push(` title: "Components/${name}",`);
765
+ lines.push(` component: ${name},`);
766
+ lines.push(` argTypes: generateArgTypes(config),`);
767
+ lines.push(` args: generateDefaultArgs(config),`);
768
+ lines.push(`}`);
769
+ lines.push(``);
770
+ lines.push(`export default meta`);
771
+ lines.push(`type Story = StoryObj<typeof ${name}>`);
772
+ lines.push(``);
773
+ lines.push(`export const Default: Story = {}`);
774
+ const variantEntries = Object.entries(variants);
775
+ if (variantEntries.length > 0) {
776
+ const [firstKey, firstValues] = variantEntries[0];
777
+ const valueKeys = Object.keys(firstValues).slice(0, 4);
778
+ for (const val of valueKeys) {
779
+ const storyName = `${firstKey.charAt(0).toUpperCase()}${firstKey.slice(1)}${val.charAt(0).toUpperCase()}${val.slice(1)}`;
780
+ lines.push(``);
781
+ lines.push(`export const ${storyName}: Story = {`);
782
+ lines.push(` args: { ${firstKey}: "${val}" },`);
783
+ lines.push(`}`);
784
+ }
785
+ }
786
+ return lines.join("\n");
787
+ }
788
+ function generateClassRenameCodemod(renames, opts = {}) {
789
+ const { format = "regex", filename = "rename-classes.mjs" } = opts;
790
+ const lines = [];
791
+ if (format === "regex") {
792
+ lines.push(`#!/usr/bin/env node`);
793
+ lines.push(`/**`);
794
+ lines.push(` * Auto-generated class rename codemod`);
795
+ lines.push(` * Usage: node ${filename} ./src`);
796
+ lines.push(` */`);
797
+ lines.push(`import fs from "node:fs"`);
798
+ lines.push(`import path from "node:path"`);
799
+ lines.push(`import { execSync } from "node:child_process"`);
800
+ lines.push(``);
801
+ lines.push(`const RENAMES = {`);
802
+ for (const [from, to] of Object.entries(renames)) {
803
+ lines.push(` "${from}": "${to}",`);
804
+ }
805
+ lines.push(`}`);
806
+ lines.push(``);
807
+ lines.push(`const dir = process.argv[2] ?? "."`);
808
+ lines.push(`const files = execSync(\`find \${dir} -name "*.tsx" -o -name "*.ts" -o -name "*.jsx"\`, { encoding: "utf-8" }).split("\\n").filter(Boolean)`);
809
+ lines.push(``);
810
+ lines.push(`let total = 0`);
811
+ lines.push(`for (const file of files) {`);
812
+ lines.push(` let content = fs.readFileSync(file, "utf-8")`);
813
+ lines.push(` let changed = false`);
814
+ lines.push(` for (const [from, to] of Object.entries(RENAMES)) {`);
815
+ lines.push(' const re = new RegExp(`\\\\b${from.replace(/[.*+?^${}()|[\\\\]\\\\]/g, "\\\\$&")}\\\\b`, "g")');
816
+ lines.push(` if (re.test(content)) { content = content.replace(re, to); changed = true; total++ }`);
817
+ lines.push(` }`);
818
+ lines.push(` if (changed) fs.writeFileSync(file, content)`);
819
+ lines.push(`}`);
820
+ lines.push(`console.log(\`Renamed \${total} occurrences in \${files.length} files\`)`);
821
+ }
822
+ return lines.join("\n");
823
+ }
824
+ function generateBarrelFile(exports$1, dir, opts = {}) {
825
+ const { includeTypes = true } = opts;
826
+ const lines = [];
827
+ lines.push(`// Auto-generated barrel file for ${dir}`);
828
+ lines.push(`// Run: npx tsx scripts/generate-barrel.ts to regenerate`);
829
+ lines.push(``);
830
+ for (const name of exports$1) {
831
+ lines.push(`export { default as ${name}, type ${name}Props } from "./${name}"`);
832
+ if (includeTypes) {
833
+ lines.push(`export type * from "./${name}"`);
834
+ }
835
+ }
836
+ return lines.join("\n");
117
837
  }
838
+ var init_codegen = __esm({
839
+ "packages/domain/shared/src/codegen.ts"() {
840
+ }
841
+ });
118
842
  function platformKey() {
119
- if (isBrowser2) return "browser";
843
+ if (isBrowser3) return "browser";
120
844
  return `${process.platform}-${process.arch}`;
121
845
  }
122
846
  function resolveNativeBinary(runtimeDir) {
123
847
  const platform = platformKey();
124
848
  const tried = [];
125
- if (isBrowser2) {
849
+ if (isBrowser3) {
126
850
  return { path: null, source: "not-found", platform, tried: ["not available in browser"] };
127
851
  }
128
- const fs9 = getNodeFs();
129
- const path11 = getNodePath2();
130
- const _req = getRequire(import.meta.url);
852
+ if (process.env.TWS_DISABLE_NATIVE === "1") {
853
+ return { path: null, source: "not-found", platform, tried: [] };
854
+ }
131
855
  const envPath = process.env.TW_NATIVE_PATH?.trim();
132
856
  if (envPath) {
133
- if (fs9.existsSync(envPath)) {
857
+ if (fs4.existsSync(envPath)) {
134
858
  return { path: envPath, source: "env", platform, tried };
135
859
  }
136
860
  tried.push(`env:${envPath} (not found)`);
137
861
  }
138
- if (process.env.TWS_NO_NATIVE === "1" || process.env.TWS_NO_RUST === "1" || process.env.TWS_DISABLE_NATIVE === "1") {
139
- return { path: null, source: "not-found", platform, tried: ["disabled by env"] };
140
- }
141
862
  const prebuiltPkgs = PLATFORM_MAP[platform] ?? [];
142
863
  for (const pkg of prebuiltPkgs) {
143
864
  try {
144
- const candidate = _req.resolve(`${pkg}/tailwind_styled_parser.node`);
145
- if (fs9.existsSync(candidate)) {
865
+ const candidate = _require.resolve(`${pkg}/tailwind_styled_parser.node`);
866
+ if (fs4.existsSync(candidate)) {
146
867
  return { path: candidate, source: "prebuilt", platform, tried };
147
868
  }
148
869
  tried.push(`prebuilt:${pkg} (resolved but missing)`);
@@ -152,30 +873,57 @@ function resolveNativeBinary(runtimeDir) {
152
873
  }
153
874
  const cwd = process.cwd();
154
875
  const base = runtimeDir ?? cwd;
155
- const localCandidates = [
156
- path11.resolve(base, "tailwind_styled_parser.node"),
157
- path11.resolve(base, "..", "tailwind_styled_parser.node"),
158
- path11.resolve(cwd, "native", "tailwind_styled_parser.node"),
159
- path11.resolve(cwd, "native", "target", "release", "tailwind_styled_parser.node"),
160
- // napi-rs conventional output
161
- path11.resolve(base, `tailwind_styled_parser.${platform}.node`)
162
- ];
876
+ const napiPlatform = platform === "linux-x64" ? "linux-x64-gnu" : platform === "linux-arm64" ? "linux-arm64-gnu" : platform;
877
+ const BINARY_NAMES = ["tailwind-styled-native", "tailwind_styled_parser"];
878
+ const localCandidates = [];
879
+ for (const bin of BINARY_NAMES) {
880
+ localCandidates.push(path6.resolve(base, `${bin}.node`));
881
+ localCandidates.push(path6.resolve(base, "..", `${bin}.node`));
882
+ localCandidates.push(path6.resolve(base, `${bin}.${platform}.node`));
883
+ localCandidates.push(path6.resolve(base, `${bin}.${napiPlatform}.node`));
884
+ }
885
+ for (const startDir of [cwd, base]) {
886
+ let dir = startDir;
887
+ for (let i = 0; i < 6; i++) {
888
+ const nativeDir = path6.resolve(dir, "native");
889
+ for (const bin of BINARY_NAMES) {
890
+ localCandidates.push(path6.resolve(nativeDir, `${bin}.node`));
891
+ localCandidates.push(path6.resolve(nativeDir, `${bin}.${platform}.node`));
892
+ localCandidates.push(path6.resolve(nativeDir, `${bin}.${napiPlatform}.node`));
893
+ localCandidates.push(path6.resolve(nativeDir, "target", "release", `${bin}.node`));
894
+ }
895
+ const parent = path6.resolve(dir, "..");
896
+ if (parent === dir) break;
897
+ dir = parent;
898
+ }
899
+ }
163
900
  for (const candidate of localCandidates) {
164
901
  tried.push(`local:${candidate}`);
165
- if (fs9.existsSync(candidate)) {
902
+ if (fs4.existsSync(candidate)) {
166
903
  return { path: candidate, source: "local", platform, tried };
167
904
  }
168
905
  }
169
906
  return { path: null, source: "not-found", platform, tried };
170
907
  }
171
- var isBrowser2, nodeModuleRef2, _nodeFs, _nodePath2, _require, PLATFORM_MAP;
908
+ function formatNativeNotFoundError(result) {
909
+ const lines = [
910
+ `[tailwind-styled] Native binding not found for ${result.platform}`,
911
+ ``,
912
+ `Tried:`,
913
+ ...result.tried.map((t) => ` - ${t}`),
914
+ ``,
915
+ `Solutions:`,
916
+ ` 1. Build locally: npm run build:rust`,
917
+ ` 2. Install prebuilt: npm install @tailwind-styled/native-${result.platform}`,
918
+ ` 3. Override path: TW_NATIVE_PATH=/path/to/parser.node`
919
+ ];
920
+ return lines.join("\n");
921
+ }
922
+ var isBrowser3, _require, PLATFORM_MAP;
172
923
  var init_native_resolution = __esm({
173
924
  "packages/domain/shared/src/native-resolution.ts"() {
174
- isBrowser2 = typeof window !== "undefined" || typeof document !== "undefined";
175
- nodeModuleRef2 = null;
176
- _nodeFs = null;
177
- _nodePath2 = null;
178
- _require = null;
925
+ isBrowser3 = typeof window !== "undefined" || typeof document !== "undefined";
926
+ _require = typeof __require !== "undefined" ? __require : createRequire(import.meta.url);
179
927
  PLATFORM_MAP = {
180
928
  "linux-x64": ["@tailwind-styled/native-linux-x64"],
181
929
  "linux-arm64": ["@tailwind-styled/native-linux-arm64"],
@@ -187,40 +935,111 @@ var init_native_resolution = __esm({
187
935
  }
188
936
  });
189
937
 
190
- // packages/domain/shared/src/index.ts
191
- function getNodeModuleRef3() {
192
- if (isBrowser3) return null;
193
- if (nodeModuleRef3 !== null) return nodeModuleRef3;
194
- try {
195
- const test = typeof __require === "function" ? __require("module") : null;
196
- nodeModuleRef3 = test;
197
- return test;
198
- } catch {
199
- nodeModuleRef3 = null;
200
- return null;
938
+ // packages/domain/shared/src/observability.ts
939
+ function createObservabilityClient(opts = {}) {
940
+ const { baseUrl = "http://localhost:7421", timeoutMs = 3e3 } = opts;
941
+ async function fetchJson(path13) {
942
+ try {
943
+ const res = await fetch(`${baseUrl}${path13}`, {
944
+ signal: AbortSignal.timeout(timeoutMs)
945
+ });
946
+ if (!res.ok) return null;
947
+ return await res.json();
948
+ } catch {
949
+ return null;
950
+ }
201
951
  }
952
+ return {
953
+ async inspectClass(className) {
954
+ const data = await fetchJson(`/inspect?class=${encodeURIComponent(className)}`);
955
+ if (!data) return null;
956
+ return { ...data, inspectedAt: Date.now() };
957
+ },
958
+ async getMetrics() {
959
+ return fetchJson("/metrics");
960
+ },
961
+ async getSummary() {
962
+ return fetchJson("/summary");
963
+ },
964
+ async getHistory() {
965
+ const data = await fetchJson("/history");
966
+ return Array.isArray(data) ? data : [];
967
+ }
968
+ };
202
969
  }
203
- function getNodeFs2() {
204
- if (isBrowser3) throw new Error("node:fs not available in browser");
205
- const nodeRequire = getNodeModuleRef3();
206
- if (!nodeRequire) throw new Error("require not available");
207
- if (!_nodeFs2) _nodeFs2 = nodeRequire.createRequire(import.meta.url)("node:fs");
208
- return _nodeFs2;
209
- }
210
- function getNodePath3() {
211
- if (isBrowser3) throw new Error("node:path not available in browser");
212
- const nodeRequire = getNodeModuleRef3();
213
- if (!nodeRequire) throw new Error("require not available");
214
- if (!_nodePath3) _nodePath3 = nodeRequire.createRequire(import.meta.url)("node:path");
215
- return _nodePath3;
216
- }
217
- function getNodeUrl2() {
218
- if (isBrowser3) throw new Error("node:url not available in browser");
219
- const nodeRequire = getNodeModuleRef3();
220
- if (!nodeRequire) throw new Error("require not available");
221
- if (!_nodeUrl2) _nodeUrl2 = nodeRequire.createRequire(import.meta.url)("node:url");
222
- return _nodeUrl2;
223
- }
970
+ var init_observability = __esm({
971
+ "packages/domain/shared/src/observability.ts"() {
972
+ }
973
+ });
974
+
975
+ // packages/domain/shared/src/index.ts
976
+ var src_exports = {};
977
+ __export(src_exports, {
978
+ ERROR_CODES: () => ERROR_CODES,
979
+ LRUCache: () => LRUCache,
980
+ NativeAnalyzerReportSchema: () => NativeAnalyzerReportSchema,
981
+ NativeCacheEntrySchema: () => NativeCacheEntrySchema,
982
+ NativeCacheReadResultSchema: () => NativeCacheReadResultSchema,
983
+ NativeCssCompileResultSchema: () => NativeCssCompileResultSchema,
984
+ NativeScanFileSchema: () => NativeScanFileSchema,
985
+ NativeScanResultSchema: () => NativeScanResultSchema,
986
+ NativeTransformResultSchema: () => NativeTransformResultSchema,
987
+ NativeWatchResultSchema: () => NativeWatchResultSchema,
988
+ PackageJsonSchema: () => PackageJsonSchema,
989
+ RegistryFileSchema: () => RegistryFileSchema,
990
+ RegistryPluginEntrySchema: () => RegistryPluginEntrySchema,
991
+ ScanCacheClassEntrySchema: () => ScanCacheClassEntrySchema,
992
+ ScanCacheSchema: () => ScanCacheSchema,
993
+ TailwindConfigSchema: () => TailwindConfigSchema,
994
+ TelemetryCollector: () => TelemetryCollector,
995
+ TwError: () => TwError,
996
+ assertTailwindV4: () => assertTailwindV4,
997
+ calculateHealth: () => calculateHealth,
998
+ createBuildTimer: () => createBuildTimer,
999
+ createDebugLogger: () => createDebugLogger,
1000
+ createEsmRequire: () => createEsmRequire,
1001
+ createLogger: () => createLogger,
1002
+ createObservabilityClient: () => createObservabilityClient,
1003
+ createTraceSnapshot: () => createTraceSnapshot,
1004
+ detectTailwind: () => detectTailwind,
1005
+ formatDuration: () => formatDuration,
1006
+ formatErrorCode: () => formatErrorCode,
1007
+ formatErrorMessage: () => formatErrorMessage,
1008
+ formatMemory: () => formatMemory,
1009
+ formatNativeNotFoundError: () => formatNativeNotFoundError,
1010
+ generateBarrelFile: () => generateBarrelFile,
1011
+ generateClassRenameCodemod: () => generateClassRenameCodemod,
1012
+ generateComponentCode: () => generateComponentCode,
1013
+ generateStorybookStory: () => generateStorybookStory,
1014
+ getBuildTimeColor: () => getBuildTimeColor,
1015
+ getDirname: () => getDirname,
1016
+ getFilename: () => getFilename,
1017
+ getGlobalTelemetry: () => getGlobalTelemetry,
1018
+ getHealthColor: () => getHealthColor,
1019
+ getMemoryColor: () => getMemoryColor,
1020
+ getModeColor: () => getModeColor,
1021
+ getPipelinePercentages: () => getPipelinePercentages,
1022
+ getSuggestion: () => getSuggestion,
1023
+ getTailwindVersion: () => getTailwindVersion,
1024
+ hashContent: () => hashContent,
1025
+ isTailwindV4: () => isTailwindV4,
1026
+ isTwError: () => isTwError,
1027
+ loadNativeBinding: () => loadNativeBinding,
1028
+ parseJsonFileWithSchema: () => parseJsonFileWithSchema,
1029
+ parseJsonWithSchema: () => parseJsonWithSchema,
1030
+ parseNative: () => parseNative,
1031
+ resetGlobalTelemetry: () => resetGlobalTelemetry,
1032
+ resolveFromRoot: () => resolveFromRoot,
1033
+ resolveLoaderPath: () => resolveLoaderPath,
1034
+ resolveNativeBinary: () => resolveNativeBinary,
1035
+ resolveNativeBindingCandidates: () => resolveNativeBindingCandidates,
1036
+ resolveNativeNodePath: () => resolveNativeNodePath,
1037
+ resolveRuntimeDir: () => resolveRuntimeDir,
1038
+ resolveWorkerPath: () => resolveWorkerPath,
1039
+ safeParseNative: () => safeParseNative,
1040
+ tryRequire: () => tryRequire,
1041
+ wrapUnknownError: () => wrapUnknownError
1042
+ });
224
1043
  function createLogger(namespace) {
225
1044
  const prefix = `[${namespace}]`;
226
1045
  return {
@@ -250,27 +1069,25 @@ function createDebugLogger(namespace, label) {
250
1069
  }
251
1070
  };
252
1071
  }
253
- function formatIssuePath(path11) {
254
- if (!path11 || path11.length === 0) return "(root)";
255
- return path11.map(
1072
+ function formatIssuePath(path13) {
1073
+ if (!path13 || path13.length === 0) return "(root)";
1074
+ return path13.map(
256
1075
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
257
1076
  ).join(".");
258
1077
  }
259
1078
  function wrapUnknownError(domain, code, error) {
260
1079
  return TwError.wrap(domain, code, error);
261
1080
  }
1081
+ function isTwError(err) {
1082
+ return err instanceof TwError;
1083
+ }
262
1084
  function loadNativeBinding(options) {
263
- if (isBrowser3) {
264
- return { binding: null, loadErrors: [{ path: "", message: "Native bindings not available in browser" }] };
265
- }
266
1085
  const { runtimeDir, candidates, isValid } = options;
267
1086
  const loadErrors = [];
268
- const path11 = getNodePath3();
269
- const fs9 = getNodeFs2();
270
1087
  for (const candidate of candidates) {
271
- const candidatePath = path11.resolve(runtimeDir, candidate);
1088
+ const candidatePath = path6__default.resolve(runtimeDir, candidate);
272
1089
  try {
273
- if (!fs9.existsSync(candidatePath) && !fs9.existsSync(candidatePath + ".node")) {
1090
+ if (!fs4__default.existsSync(candidatePath) && !fs4__default.existsSync(candidatePath + ".node")) {
274
1091
  continue;
275
1092
  }
276
1093
  const mod = requireNativeModule(candidatePath);
@@ -284,74 +1101,76 @@ function loadNativeBinding(options) {
284
1101
  }
285
1102
  return { binding: null, loadErrors };
286
1103
  }
287
- function getRequire2() {
288
- if (isBrowser3) return (() => {
289
- throw new Error("require not available in browser");
290
- });
291
- const nodeRequire = getNodeModuleRef3();
292
- if (!nodeRequire) return (() => {
293
- throw new Error("require not available");
294
- });
295
- return nodeRequire.createRequire(import.meta.url);
296
- }
297
- function requireNativeModule(path11) {
298
- return _require2(path11);
1104
+ function requireNativeModule(p) {
1105
+ return _require2(p);
299
1106
  }
300
1107
  function resolveNativeBindingCandidates(options) {
301
- if (isBrowser3) return [];
302
- const { runtimeDir, envVarNames = [], includeDefaultCandidates = true, enforceNodeExtensionForEnvPath = false } = options;
1108
+ const {
1109
+ envVarNames = ["TW_NATIVE_PATH", "TWS_NATIVE_PATH"],
1110
+ includeDefaultCandidates = true,
1111
+ enforceNodeExtensionForEnvPath = false
1112
+ } = options;
1113
+ const runtimeDir = options.runtimeDir || process.cwd();
303
1114
  const candidates = [];
304
- const path11 = getNodePath3();
305
- const fs9 = getNodeFs2();
306
1115
  for (const envVar of envVarNames) {
307
1116
  const envPath = process.env[envVar];
308
1117
  if (envPath) {
309
- if (enforceNodeExtensionForEnvPath && !envPath.endsWith(".node")) {
310
- candidates.push(envPath + ".node");
311
- } else {
312
- candidates.push(envPath);
313
- }
1118
+ candidates.push(enforceNodeExtensionForEnvPath && !envPath.endsWith(".node") ? envPath + ".node" : envPath);
314
1119
  }
315
1120
  }
316
1121
  if (!includeDefaultCandidates) return candidates;
317
- if (fs9.existsSync(runtimeDir)) {
1122
+ if (fs4__default.existsSync(runtimeDir)) {
318
1123
  try {
319
- const entries = fs9.readdirSync(runtimeDir);
320
- for (const entry of entries) {
321
- if (entry.endsWith(".node")) {
322
- candidates.push(entry);
323
- }
1124
+ for (const entry of fs4__default.readdirSync(runtimeDir)) {
1125
+ if (entry.endsWith(".node")) candidates.push(entry);
324
1126
  }
325
1127
  } catch {
326
1128
  }
327
1129
  }
328
- const platform = typeof process !== "undefined" ? process.platform : "";
329
- const ext = platform === "win32" ? ".dll" : platform === "darwin" ? ".dylib" : ".so";
330
- const defaultBindingName = `tailwind_styled_parser${ext}`;
331
- candidates.push(path11.resolve(runtimeDir, "..", "..", "..", "native", defaultBindingName));
332
- candidates.push(path11.resolve(runtimeDir, "..", "..", "..", "..", "native", defaultBindingName));
333
- candidates.push(path11.resolve(process.cwd(), "native", defaultBindingName));
1130
+ const BINARY_NAMES = ["tailwind-styled-native", "tailwind_styled_parser"];
1131
+ const napiPlatform = process.platform === "linux" && process.arch === "x64" ? "linux-x64-gnu" : process.platform === "linux" && process.arch === "arm64" ? "linux-arm64-gnu" : `${process.platform}-${process.arch}`;
1132
+ for (const bin of BINARY_NAMES) {
1133
+ candidates.push(path6__default.resolve(runtimeDir, `${bin}.node`));
1134
+ candidates.push(path6__default.resolve(runtimeDir, `${bin}.${napiPlatform}.node`));
1135
+ candidates.push(path6__default.resolve(runtimeDir, "..", "..", "..", "..", "native", `${bin}.node`));
1136
+ candidates.push(path6__default.resolve(runtimeDir, "..", "..", "..", "..", "native", `${bin}.${napiPlatform}.node`));
1137
+ candidates.push(path6__default.resolve(runtimeDir, "..", "..", "..", "native", `${bin}.node`));
1138
+ candidates.push(path6__default.resolve(process.cwd(), "native", `${bin}.node`));
1139
+ candidates.push(path6__default.resolve(process.cwd(), "native", `${bin}.${napiPlatform}.node`));
1140
+ }
334
1141
  return Array.from(new Set(candidates));
335
1142
  }
336
1143
  function resolveRuntimeDir(dir, importMetaUrl) {
337
- if (isBrowser3) return "";
338
- if (dir) return getNodePath3().resolve(dir);
1144
+ if (dir) return path6__default.resolve(dir);
339
1145
  try {
340
- return getNodeUrl2().fileURLToPath(importMetaUrl);
1146
+ return path6__default.dirname(fileURLToPath(importMetaUrl));
341
1147
  } catch {
342
1148
  return process.cwd();
343
1149
  }
344
1150
  }
345
- var isBrowser3, nodeModuleRef3, _nodeFs2, _nodePath3, _nodeUrl2, TwError, _require2;
1151
+ function hashContent(content, algorithm = "md5", length) {
1152
+ const hash = createHash(algorithm).update(content).digest("hex");
1153
+ return length ? hash.slice(0, length) : hash;
1154
+ }
1155
+ function formatErrorMessage(error) {
1156
+ if (error instanceof TwError) return error.toString();
1157
+ if (error instanceof Error) return error.message;
1158
+ return String(error);
1159
+ }
1160
+ var TwError, _require2, LRUCache;
346
1161
  var init_src = __esm({
347
1162
  "packages/domain/shared/src/index.ts"() {
1163
+ init_trace();
1164
+ init_error_codes();
1165
+ init_compatibility();
1166
+ init_native_schemas();
348
1167
  init_esmHelpers();
1168
+ init_telemetry();
1169
+ init_configSchemas();
1170
+ init_workerResolver();
1171
+ init_codegen();
349
1172
  init_native_resolution();
350
- isBrowser3 = typeof window !== "undefined" || typeof document !== "undefined";
351
- nodeModuleRef3 = null;
352
- _nodeFs2 = null;
353
- _nodePath3 = null;
354
- _nodeUrl2 = null;
1173
+ init_observability();
355
1174
  TwError = class _TwError extends Error {
356
1175
  /** @deprecated Gunakan source */
357
1176
  domain;
@@ -385,8 +1204,8 @@ var init_src = __esm({
385
1204
  /** Buat TwError dari ZodError — dukung shape Zod v3 (`errors`) dan v4 (`issues`). */
386
1205
  static fromZod(err) {
387
1206
  const first = err.issues?.[0] ?? err.errors?.[0];
388
- const path11 = formatIssuePath(first?.path);
389
- const message = first ? `${path11}: ${first.message}` : "Schema validation failed";
1207
+ const path13 = formatIssuePath(first?.path);
1208
+ const message = first ? `${path13}: ${first.message}` : "Schema validation failed";
390
1209
  return new _TwError("validation", "SCHEMA_VALIDATION_FAILED", message, err);
391
1210
  }
392
1211
  static wrap(source, code, err) {
@@ -404,13 +1223,57 @@ var init_src = __esm({
404
1223
  return `[${this.source.toUpperCase()}:${this.code}] ${this.message}`;
405
1224
  }
406
1225
  };
407
- _require2 = getRequire2();
1226
+ _require2 = createRequire(import.meta.url);
1227
+ LRUCache = class {
1228
+ capacity;
1229
+ cache;
1230
+ constructor(capacity) {
1231
+ this.capacity = capacity;
1232
+ this.cache = /* @__PURE__ */ new Map();
1233
+ }
1234
+ get(key) {
1235
+ if (!this.cache.has(key)) return void 0;
1236
+ const value = this.cache.get(key);
1237
+ this.cache.delete(key);
1238
+ this.cache.set(key, value);
1239
+ return value;
1240
+ }
1241
+ set(key, value) {
1242
+ if (this.cache.has(key)) {
1243
+ this.cache.delete(key);
1244
+ } else if (this.cache.size >= this.capacity) {
1245
+ const firstKey = this.cache.keys().next().value;
1246
+ if (firstKey !== void 0) {
1247
+ this.cache.delete(firstKey);
1248
+ }
1249
+ }
1250
+ this.cache.set(key, value);
1251
+ }
1252
+ delete(key) {
1253
+ return this.cache.delete(key);
1254
+ }
1255
+ has(key) {
1256
+ return this.cache.has(key);
1257
+ }
1258
+ clear() {
1259
+ this.cache.clear();
1260
+ }
1261
+ entries() {
1262
+ return this.cache.entries();
1263
+ }
1264
+ get size() {
1265
+ return this.cache.size;
1266
+ }
1267
+ };
408
1268
  }
409
1269
  });
410
- var log, NATIVE_UNAVAILABLE_MESSAGE, nativeBridge, bridgeLoadAttempted, bridgeLoadError, isValidNativeBridge, getNativeBridge;
1270
+
1271
+ // packages/domain/compiler/src/nativeBridge.ts
1272
+ var _loadNative, log, NATIVE_UNAVAILABLE_MESSAGE, nativeBridge, bridgeLoadAttempted, bridgeLoadError, isValidNativeBridge, getNativeBridge;
411
1273
  var init_nativeBridge = __esm({
412
1274
  "packages/domain/compiler/src/nativeBridge.ts"() {
413
1275
  init_src();
1276
+ _loadNative = (path13) => __require(path13);
414
1277
  log = (...args) => {
415
1278
  if (process.env.DEBUG?.includes("compiler:native")) {
416
1279
  console.log("[compiler:native]", ...args);
@@ -437,11 +1300,10 @@ var init_nativeBridge = __esm({
437
1300
  bridgeLoadAttempted = true;
438
1301
  try {
439
1302
  const runtimeDir = resolveRuntimeDir(void 0, import.meta.url);
440
- const require3 = createRequire(import.meta.url);
441
1303
  const result = resolveNativeBinary(runtimeDir);
442
1304
  if (result.path && result.path.endsWith(".node")) {
443
1305
  try {
444
- const binding = require3(result.path);
1306
+ const binding = _loadNative(result.path);
445
1307
  if (isValidNativeBridge(binding)) {
446
1308
  nativeBridge = binding;
447
1309
  log("Native bridge loaded successfully from:", result.path);
@@ -473,6 +1335,7 @@ Tried paths: ${result.tried.join("\n")}`);
473
1335
  var tailwindEngine_exports = {};
474
1336
  __export(tailwindEngine_exports, {
475
1337
  generateRawCss: () => generateRawCss,
1338
+ processTailwindCssWithTargets: () => processTailwindCssWithTargets,
476
1339
  runCssPipeline: () => runCssPipeline,
477
1340
  runCssPipelineSync: () => runCssPipelineSync
478
1341
  });
@@ -500,12 +1363,11 @@ function generateRawCss(classes) {
500
1363
  function postProcessWithLightning(rawCss) {
501
1364
  if (!rawCss) return "";
502
1365
  const native = getNativeBridge();
503
- if (typeof native.processTailwindCssLightning === "function") {
504
- const result = native.processTailwindCssLightning(rawCss);
505
- return result?.css ?? rawCss;
1366
+ if (typeof native.processTailwindCssLightning !== "function") {
1367
+ throw new Error("FATAL: Native binding 'processTailwindCssLightning' is required but not available.");
506
1368
  }
507
- console.warn("[tailwind-styled] processTailwindCssLightning tidak tersedia \u2014 gunakan raw CSS");
508
- return rawCss;
1369
+ const result = native.processTailwindCssLightning(rawCss);
1370
+ return result?.css ?? rawCss;
509
1371
  }
510
1372
  async function runCssPipeline(classes) {
511
1373
  const unique = [...new Set(classes.filter(Boolean))];
@@ -539,6 +1401,14 @@ function runCssPipelineSync(classes) {
539
1401
  optimized: hasLightning
540
1402
  };
541
1403
  }
1404
+ function processTailwindCssWithTargets(css, targets) {
1405
+ const native = getNativeBridge();
1406
+ if (!native?.processTailwindCssWithTargets) {
1407
+ throw new Error("FATAL: Native binding 'processTailwindCssWithTargets' is required but not available.");
1408
+ }
1409
+ const result = native.processTailwindCssWithTargets(css, targets ?? null);
1410
+ return (result?.css ?? css).trim();
1411
+ }
542
1412
  var require2, _twEngine, _twEngineError;
543
1413
  var init_tailwindEngine = __esm({
544
1414
  "packages/domain/compiler/src/tailwindEngine.ts"() {
@@ -552,14 +1422,26 @@ var init_tailwindEngine = __esm({
552
1422
  // packages/domain/scanner/src/native-bridge.ts
553
1423
  var native_bridge_exports = {};
554
1424
  __export(native_bridge_exports, {
1425
+ batchExtractClassesNative: () => batchExtractClassesNative,
555
1426
  cachePriorityNative: () => cachePriorityNative,
556
1427
  cacheReadNative: () => cacheReadNative,
557
1428
  cacheWriteNative: () => cacheWriteNative,
1429
+ collectFilesNative: () => collectFilesNative,
1430
+ computeCacheStatsNative: () => computeCacheStatsNative,
558
1431
  extractClassesNative: () => extractClassesNative,
1432
+ generateSubComponentTypesNative: () => generateSubComponentTypesNative,
559
1433
  hasNativeScannerBinding: () => hasNativeScannerBinding,
560
1434
  hashContentNative: () => hashContentNative,
561
1435
  isRustCacheAvailable: () => isRustCacheAvailable,
1436
+ pruneStaleEntriesNative: () => pruneStaleEntriesNative,
1437
+ rebuildWorkspaceResultNative: () => rebuildWorkspaceResultNative,
562
1438
  resetScannerBridgeCache: () => resetScannerBridgeCache,
1439
+ scanCacheGet: () => scanCacheGet,
1440
+ scanCacheInvalidate: () => scanCacheInvalidate,
1441
+ scanCachePut: () => scanCachePut,
1442
+ scanCacheStats: () => scanCacheStats,
1443
+ scanFileNative: () => scanFileNative,
1444
+ scanFilesBatchNative: () => scanFilesBatchNative,
563
1445
  scanWorkspaceNative: () => scanWorkspaceNative
564
1446
  });
565
1447
  function getDirname2() {
@@ -567,7 +1449,7 @@ function getDirname2() {
567
1449
  return __dirname;
568
1450
  }
569
1451
  if (typeof import.meta !== "undefined" && import.meta.url) {
570
- return path3.dirname(fileURLToPath(import.meta.url));
1452
+ return path6__default.dirname(fileURLToPath(import.meta.url));
571
1453
  }
572
1454
  return process.cwd();
573
1455
  }
@@ -648,6 +1530,95 @@ function cachePriorityNative(mtimeMs, size, cachedMtimeMs, cachedSize, cachedHit
648
1530
  }
649
1531
  return result;
650
1532
  }
1533
+ function batchExtractClassesNative(filePaths) {
1534
+ const binding = scannerGetBinding();
1535
+ if (!binding.batchExtractClasses) {
1536
+ throw new Error("FATAL: Native binding 'batchExtractClasses' is required but not available.");
1537
+ }
1538
+ return binding.batchExtractClasses(filePaths) ?? [];
1539
+ }
1540
+ function scanCacheGet(filePath, contentHash) {
1541
+ const binding = scannerGetBinding();
1542
+ if (!binding.scanCacheGet) {
1543
+ throw new Error("FATAL: Native binding 'scanCacheGet' is required but not available.");
1544
+ }
1545
+ return binding.scanCacheGet(filePath, contentHash) ?? null;
1546
+ }
1547
+ function scanCachePut(filePath, contentHash, classes, mtimeMs, size) {
1548
+ const binding = scannerGetBinding();
1549
+ if (!binding.scanCachePut) {
1550
+ throw new Error("FATAL: Native binding 'scanCachePut' is required but not available.");
1551
+ }
1552
+ binding.scanCachePut(filePath, contentHash, classes, mtimeMs, size);
1553
+ }
1554
+ function scanCacheInvalidate(filePath) {
1555
+ const binding = scannerGetBinding();
1556
+ if (!binding.scanCacheInvalidate) {
1557
+ throw new Error("FATAL: Native binding 'scanCacheInvalidate' is required but not available.");
1558
+ }
1559
+ binding.scanCacheInvalidate(filePath);
1560
+ }
1561
+ function scanCacheStats() {
1562
+ const binding = scannerGetBinding();
1563
+ if (!binding.scanCacheStats) {
1564
+ throw new Error("FATAL: Native binding 'scanCacheStats' is required but not available.");
1565
+ }
1566
+ return binding.scanCacheStats();
1567
+ }
1568
+ function scanFileNative(filePath) {
1569
+ const binding = scannerGetBinding();
1570
+ if (!binding.scanFile) {
1571
+ throw new Error("FATAL: Native binding 'scanFile' is required but not available.");
1572
+ }
1573
+ return binding.scanFile(filePath);
1574
+ }
1575
+ function collectFilesNative(root, extensions, ignoreDirs) {
1576
+ const binding = scannerGetBinding();
1577
+ if (!binding.collectFiles) return null;
1578
+ return binding.collectFiles(root, extensions, ignoreDirs);
1579
+ }
1580
+ function scanFilesBatchNative(filePaths) {
1581
+ const binding = scannerGetBinding();
1582
+ if (!binding.scanFilesBatch) {
1583
+ return filePaths.map((fp) => {
1584
+ try {
1585
+ const r = binding.scanFile?.(fp);
1586
+ return r ? { file: r.file, classes: r.classes, hash: r.hash ?? "" } : { file: fp, classes: [], hash: "" };
1587
+ } catch {
1588
+ return { file: fp, classes: [], hash: "" };
1589
+ }
1590
+ });
1591
+ }
1592
+ return binding.scanFilesBatch(filePaths);
1593
+ }
1594
+ function generateSubComponentTypesNative(root, outputPath) {
1595
+ const binding = scannerGetBinding();
1596
+ if (!binding.generateSubComponentTypes) return null;
1597
+ return binding.generateSubComponentTypes(root, outputPath ?? null);
1598
+ }
1599
+ function pruneStaleEntriesNative(entries, maxAgeMs, checkExists) {
1600
+ const binding = scannerGetBinding();
1601
+ if (!binding.pruneStaleEntries) return null;
1602
+ return binding.pruneStaleEntries(
1603
+ entries.map((e) => ({ file: e.file, lastSeenMs: e.lastSeenMs ?? 0 })),
1604
+ maxAgeMs ?? null,
1605
+ checkExists ?? null
1606
+ );
1607
+ }
1608
+ function rebuildWorkspaceResultNative(files) {
1609
+ const binding = scannerBridgeLoader.get();
1610
+ if (!binding?.rebuildWorkspaceResult) return null;
1611
+ try {
1612
+ return binding.rebuildWorkspaceResult(files);
1613
+ } catch {
1614
+ return null;
1615
+ }
1616
+ }
1617
+ function computeCacheStatsNative(filesClasses, sizes, top) {
1618
+ const binding = scannerGetBinding();
1619
+ if (!binding.computeCacheStats) return null;
1620
+ return binding.computeCacheStats(filesClasses, sizes, top ?? null);
1621
+ }
651
1622
  var log2, isValidScannerBinding, createScannerBridgeLoader, scannerBridgeLoader, scannerGetBinding, resetScannerBridgeCache;
652
1623
  var init_native_bridge = __esm({
653
1624
  "packages/domain/scanner/src/native-bridge.ts"() {
@@ -731,74 +1702,9 @@ var init_native_bridge = __esm({
731
1702
  resetScannerBridgeCache = scannerBridgeLoader.reset;
732
1703
  }
733
1704
  });
734
-
735
- // packages/domain/compiler/src/index.ts
736
- init_nativeBridge();
737
- var transformSource = (source, opts) => {
738
- const native = getNativeBridge();
739
- if (!native?.transformSource) {
740
- throw new Error("FATAL: Native binding 'transformSource' is required but not available.");
741
- }
742
- const result = native.transformSource(source, opts);
743
- if (!result) {
744
- throw new Error("FATAL: transformSource returned null");
745
- }
746
- return result;
747
- };
748
- var generateCssForClasses = async (classes, _tailwindConfig, _root) => {
749
- const { runCssPipeline: runCssPipeline2 } = await Promise.resolve().then(() => (init_tailwindEngine(), tailwindEngine_exports));
750
- const result = await runCssPipeline2(classes);
751
- return result.css;
752
- };
753
- var mergeClassesStatic = (classes) => {
754
- const result = normalizeAndDedupClasses(classes);
755
- return result?.normalized || "";
756
- };
757
- function normalizeAndDedupClassesJs(raw) {
758
- const seen = /* @__PURE__ */ new Set();
759
- const result = [];
760
- let duplicatesRemoved = 0;
761
- for (const token of raw.split(/\s+/)) {
762
- if (token.length === 0) continue;
763
- if (seen.has(token)) {
764
- duplicatesRemoved++;
765
- } else {
766
- seen.add(token);
767
- result.push(token);
768
- }
769
- }
770
- return {
771
- normalized: result.join(" "),
772
- duplicatesRemoved,
773
- uniqueCount: result.length
774
- };
775
- }
776
- var normalizeAndDedupClasses = (raw) => {
777
- const native = getNativeBridge();
778
- if (!native?.normalizeAndDedupClasses) {
779
- return normalizeAndDedupClassesJs(raw);
780
- }
781
- const result = native.normalizeAndDedupClasses(raw);
782
- return result || { normalized: "", duplicatesRemoved: 0, uniqueCount: 0 };
783
- };
784
- var runLoaderTransform = (ctx) => {
785
- const { filepath, source, options } = ctx;
786
- const result = transformSource(source, { filename: filepath, ...options });
787
- return {
788
- code: result?.code || "",
789
- changed: result?.changed || false,
790
- classes: result?.classes || []
791
- };
792
- };
793
-
794
- // packages/domain/scanner/src/index.ts
795
- init_src();
796
-
797
- // packages/domain/scanner/src/cache-native.ts
798
- init_native_bridge();
799
1705
  function defaultCachePath(rootDir, cacheDir) {
800
- const dir = cacheDir ? path3.resolve(rootDir, cacheDir) : path3.join(process.cwd(), ".cache", "tailwind-styled");
801
- return path3.join(dir, "scanner-cache.json");
1706
+ const dir = cacheDir ? path6__default.resolve(rootDir, cacheDir) : path6__default.join(process.cwd(), ".cache", "tailwind-styled");
1707
+ return path6__default.join(dir, "scanner-cache.json");
802
1708
  }
803
1709
  function readCache(rootDir, cacheDir) {
804
1710
  const cachePath = defaultCachePath(rootDir, cacheDir);
@@ -834,158 +1740,219 @@ function filePriority(mtimeMs, size, cached, nowMs = Date.now()) {
834
1740
  nowMs
835
1741
  );
836
1742
  }
837
-
838
- // packages/domain/scanner/src/index.ts
839
- init_native_bridge();
840
-
841
- // packages/domain/scanner/src/schemas.ts
842
- init_src();
843
- var formatIssuePath2 = (path11) => path11.length > 0 ? path11.map(
844
- (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
845
- ).join(".") : "<root>";
846
- var formatIssues = (error) => error.issues.map((issue) => {
847
- const path11 = formatIssuePath2(issue.path);
848
- return `${path11}: ${issue.message}`;
849
- }).join("; ");
850
- var parseWithSchema = (schema, data, label) => {
851
- const parsed = schema.safeParse(data);
852
- if (parsed.success) return parsed.data;
853
- const details = formatIssues(parsed.error);
854
- throw new TwError(
855
- "validation",
856
- "SCHEMA_VALIDATION_FAILED",
857
- details ? `${label}: ${details}` : label,
858
- parsed.error
859
- );
860
- };
861
- var NonNegativeIntegerSchema = z.number().int().min(0);
862
- var ScanWorkspaceOptionsSchema = z.object({
863
- includeExtensions: z.array(z.string()).optional(),
864
- ignoreDirectories: z.array(z.string()).optional(),
865
- useCache: z.boolean().optional(),
866
- cacheDir: z.string().min(1).optional(),
867
- smartInvalidation: z.boolean().optional()
868
- });
869
- var ScanFileResultSchema = z.object({
870
- file: z.string(),
871
- classes: z.array(z.string()),
872
- hash: z.string().optional()
873
- });
874
- var ScanWorkspaceResultSchema = z.object({
875
- files: z.array(ScanFileResultSchema),
876
- totalFiles: NonNegativeIntegerSchema,
877
- uniqueClasses: z.array(z.string())
878
- }).refine((value) => value.totalFiles === value.files.length, {
879
- message: "scan result totalFiles must match files.length",
880
- path: ["totalFiles"]
881
- });
882
- z.object({
883
- rootDir: z.string().min(1),
884
- options: ScanWorkspaceOptionsSchema.optional()
1743
+ var init_cache_native = __esm({
1744
+ "packages/domain/scanner/src/cache-native.ts"() {
1745
+ init_native_bridge();
1746
+ }
885
1747
  });
886
- var ScannerWorkerSuccessMessageSchema = z.object({
887
- ok: z.literal(true),
888
- result: ScanWorkspaceResultSchema
1748
+ function collectFiles(rootDir, extensions, ignoreDirs) {
1749
+ const native = collectFilesNative(rootDir, extensions, ignoreDirs);
1750
+ if (native !== null) return native;
1751
+ const files = [];
1752
+ function walk(dir) {
1753
+ let entries;
1754
+ try {
1755
+ entries = fs4__default.readdirSync(dir, { withFileTypes: true });
1756
+ } catch {
1757
+ return;
1758
+ }
1759
+ for (const entry of entries) {
1760
+ const fullPath = path6__default.join(dir, entry.name);
1761
+ const rel = path6__default.relative(rootDir, fullPath);
1762
+ if (entry.isDirectory()) {
1763
+ const ignored = ignoreDirs.some((d) => entry.name === d || rel.startsWith(d + path6__default.sep));
1764
+ if (!ignored) walk(fullPath);
1765
+ } else if (isScannableFile(entry.name, extensions)) {
1766
+ files.push(fullPath);
1767
+ }
1768
+ }
1769
+ }
1770
+ walk(rootDir);
1771
+ return files;
1772
+ }
1773
+ function mergeResults(batchResults) {
1774
+ const files = batchResults.map((r) => ({
1775
+ file: r.file,
1776
+ classes: r.classes,
1777
+ hash: r.content_hash
1778
+ }));
1779
+ const native = rebuildWorkspaceResultNative(files);
1780
+ if (native) return native;
1781
+ const unique = new Set(files.flatMap((f) => f.classes));
1782
+ return { files, totalFiles: files.length, uniqueClasses: Array.from(unique).sort() };
1783
+ }
1784
+ function runChunkInWorker(filePaths) {
1785
+ return new Promise((resolve2, reject) => {
1786
+ const worker = new Worker(_workerFilename, {
1787
+ workerData: { filePaths }
1788
+ });
1789
+ worker.once("message", (payload) => {
1790
+ if (payload.ok) {
1791
+ resolve2(payload.results);
1792
+ } else {
1793
+ reject(new Error(payload.error ?? "parallel-scanner worker failed"));
1794
+ }
1795
+ });
1796
+ worker.once("error", reject);
1797
+ worker.once("exit", (code) => {
1798
+ if (code !== 0) reject(new Error(`parallel-scanner worker exited with code ${code}`));
1799
+ });
1800
+ });
1801
+ }
1802
+ async function scanWorkspaceParallel(rootDir, options = {}) {
1803
+ const {
1804
+ extensions = DEFAULT_EXTENSIONS,
1805
+ ignoreDirs = DEFAULT_IGNORES,
1806
+ maxWorkers = Math.max(1, availableParallelism() - 1),
1807
+ chunkSize = DEFAULT_CHUNK_SIZE
1808
+ } = options;
1809
+ const files = collectFiles(path6__default.resolve(rootDir), extensions, ignoreDirs);
1810
+ if (files.length < PARALLEL_THRESHOLD) {
1811
+ return mergeResults(batchExtractClassesNative(files));
1812
+ }
1813
+ const chunks = [];
1814
+ for (let i = 0; i < files.length; i += chunkSize) {
1815
+ chunks.push(files.slice(i, i + chunkSize));
1816
+ }
1817
+ const allResults = [];
1818
+ for (let i = 0; i < chunks.length; i += maxWorkers) {
1819
+ const batch = chunks.slice(i, i + maxWorkers);
1820
+ const batchResults = await Promise.all(batch.map(runChunkInWorker));
1821
+ allResults.push(...batchResults.flat());
1822
+ }
1823
+ return mergeResults(allResults);
1824
+ }
1825
+ var PARALLEL_THRESHOLD, DEFAULT_CHUNK_SIZE, _workerFilename;
1826
+ var init_parallel_scanner = __esm({
1827
+ "packages/domain/scanner/src/parallel-scanner.ts"() {
1828
+ init_src2();
1829
+ init_native_bridge();
1830
+ PARALLEL_THRESHOLD = 50;
1831
+ DEFAULT_CHUNK_SIZE = 150;
1832
+ if (!isMainThread && parentPort) {
1833
+ const { filePaths } = workerData;
1834
+ try {
1835
+ const results = batchExtractClassesNative(filePaths);
1836
+ const msg = { ok: true, results };
1837
+ parentPort.postMessage(msg);
1838
+ } catch (error) {
1839
+ const msg = {
1840
+ ok: false,
1841
+ error: error instanceof Error ? error.message : String(error)
1842
+ };
1843
+ parentPort.postMessage(msg);
1844
+ }
1845
+ }
1846
+ _workerFilename = typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url);
1847
+ }
889
1848
  });
890
- var ScannerWorkerErrorMessageSchema = z.object({
891
- ok: z.literal(false),
892
- error: z.string().optional()
1849
+ var formatIssuePath2, formatIssues, parseWithSchema, NonNegativeIntegerSchema, ScanWorkspaceOptionsSchema, ScanFileResultSchema, ScanWorkspaceResultSchema, ScannerWorkerSuccessMessageSchema, ScannerWorkerErrorMessageSchema, ScannerWorkerMessageSchema, parseScanWorkspaceOptions, parseScanWorkspaceResult, parseScannerWorkerMessage;
1850
+ var init_schemas = __esm({
1851
+ "packages/domain/scanner/src/schemas.ts"() {
1852
+ init_src();
1853
+ formatIssuePath2 = (path13) => path13.length > 0 ? path13.map(
1854
+ (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
1855
+ ).join(".") : "<root>";
1856
+ formatIssues = (error) => error.issues.map((issue) => {
1857
+ const path13 = formatIssuePath2(issue.path);
1858
+ return `${path13}: ${issue.message}`;
1859
+ }).join("; ");
1860
+ parseWithSchema = (schema, data, label) => {
1861
+ const parsed = schema.safeParse(data);
1862
+ if (parsed.success) return parsed.data;
1863
+ const details = formatIssues(parsed.error);
1864
+ throw new TwError(
1865
+ "validation",
1866
+ "SCHEMA_VALIDATION_FAILED",
1867
+ details ? `${label}: ${details}` : label,
1868
+ parsed.error
1869
+ );
1870
+ };
1871
+ NonNegativeIntegerSchema = z.number().int().min(0);
1872
+ ScanWorkspaceOptionsSchema = z.object({
1873
+ includeExtensions: z.array(z.string()).optional(),
1874
+ ignoreDirectories: z.array(z.string()).optional(),
1875
+ useCache: z.boolean().optional(),
1876
+ cacheDir: z.string().min(1).optional(),
1877
+ smartInvalidation: z.boolean().optional()
1878
+ });
1879
+ ScanFileResultSchema = z.object({
1880
+ file: z.string(),
1881
+ classes: z.array(z.string()),
1882
+ hash: z.string().optional()
1883
+ });
1884
+ ScanWorkspaceResultSchema = z.object({
1885
+ files: z.array(ScanFileResultSchema),
1886
+ totalFiles: NonNegativeIntegerSchema,
1887
+ uniqueClasses: z.array(z.string())
1888
+ }).refine((value) => value.totalFiles === value.files.length, {
1889
+ message: "scan result totalFiles must match files.length",
1890
+ path: ["totalFiles"]
1891
+ });
1892
+ z.object({
1893
+ rootDir: z.string().min(1),
1894
+ options: ScanWorkspaceOptionsSchema.optional()
1895
+ });
1896
+ ScannerWorkerSuccessMessageSchema = z.object({
1897
+ ok: z.literal(true),
1898
+ result: ScanWorkspaceResultSchema
1899
+ });
1900
+ ScannerWorkerErrorMessageSchema = z.object({
1901
+ ok: z.literal(false),
1902
+ error: z.string().optional()
1903
+ });
1904
+ ScannerWorkerMessageSchema = z.union([
1905
+ ScannerWorkerSuccessMessageSchema,
1906
+ ScannerWorkerErrorMessageSchema
1907
+ ]);
1908
+ parseScanWorkspaceOptions = (options) => parseWithSchema(ScanWorkspaceOptionsSchema, options ?? {}, "scanner options are invalid");
1909
+ parseScanWorkspaceResult = (result) => parseWithSchema(ScanWorkspaceResultSchema, result, "scanner workspace result is invalid");
1910
+ parseScannerWorkerMessage = (message) => parseWithSchema(ScannerWorkerMessageSchema, message, "scanner worker message is invalid");
1911
+ }
893
1912
  });
894
- var ScannerWorkerMessageSchema = z.union([
895
- ScannerWorkerSuccessMessageSchema,
896
- ScannerWorkerErrorMessageSchema
897
- ]);
898
- var parseScanWorkspaceOptions = (options) => parseWithSchema(ScanWorkspaceOptionsSchema, options ?? {}, "scanner options are invalid");
899
- var parseScanWorkspaceResult = (result) => parseWithSchema(ScanWorkspaceResultSchema, result, "scanner workspace result is invalid");
900
- var parseScannerWorkerMessage = (message) => parseWithSchema(ScannerWorkerMessageSchema, message, "scanner worker message is invalid");
901
1913
 
902
1914
  // packages/domain/scanner/src/index.ts
903
- var log3 = createLogger("scanner");
904
- var SCAN_WORKER_TIMEOUT_MS = 12e4;
1915
+ var src_exports2 = {};
1916
+ __export(src_exports2, {
1917
+ DEFAULT_EXTENSIONS: () => DEFAULT_EXTENSIONS,
1918
+ DEFAULT_IGNORES: () => DEFAULT_IGNORES,
1919
+ batchExtractClassesNative: () => batchExtractClassesNative,
1920
+ extractClassesNative: () => extractClassesNative,
1921
+ isScannableFile: () => isScannableFile,
1922
+ parseScanWorkspaceOptions: () => parseScanWorkspaceOptions,
1923
+ parseScanWorkspaceResult: () => parseScanWorkspaceResult,
1924
+ parseScannerWorkerMessage: () => parseScannerWorkerMessage,
1925
+ scanFile: () => scanFile,
1926
+ scanSource: () => scanSource,
1927
+ scanWorkspace: () => scanWorkspace,
1928
+ scanWorkspaceAsync: () => scanWorkspaceAsync
1929
+ });
905
1930
  function getRuntimeDir() {
906
1931
  if (typeof __dirname !== "undefined" && __dirname.length > 0) {
907
1932
  return __dirname;
908
1933
  }
909
1934
  if (typeof import.meta !== "undefined" && import.meta.url) {
910
- return path3.dirname(fileURLToPath(import.meta.url));
1935
+ return path6__default.dirname(fileURLToPath(import.meta.url));
911
1936
  }
912
1937
  return process.cwd();
913
- }
914
- var createNativeParserLoader = () => {
915
- const _state = {
916
- binding: void 0,
917
- initError: null
918
- };
919
- const debugNative = (message) => {
920
- log3.debug(`[native] ${message}`);
921
- };
922
- const loadNativeParserBinding = () => {
923
- if (_state.binding !== void 0) return _state.binding;
924
- const runtimeDir = getRuntimeDir();
925
- const req = createRequire(path3.join(runtimeDir, "noop.cjs"));
926
- const candidates = [
927
- path3.resolve(process.cwd(), "native/tailwind_styled_parser.node"),
928
- path3.resolve(process.cwd(), "native/build/Release/tailwind_styled_parser.node"),
929
- path3.resolve(runtimeDir, "..", "..", "..", "native", "tailwind_styled_parser.node"),
930
- path3.resolve(
931
- runtimeDir,
932
- "..",
933
- "..",
934
- "..",
935
- "native",
936
- "build",
937
- "Release",
938
- "tailwind_styled_parser.node"
939
- )
940
- ];
941
- for (const fullPath of candidates) {
942
- if (!fs.existsSync(fullPath)) continue;
943
- try {
944
- const required = req(fullPath);
945
- if (required && (typeof required.extractClassesFromSource === "function" || typeof required.parseClasses === "function" || typeof required.parse_classes === "function")) {
946
- _state.binding = required;
947
- debugNative(`using native parser from ${fullPath}`);
948
- return _state.binding;
949
- }
950
- } catch (error) {
951
- _state.initError = error instanceof Error ? error.message : String(error);
952
- }
953
- }
954
- _state.binding = null;
955
- if (!_state.initError) {
956
- _state.initError = "native .node binding not found";
957
- }
958
- debugNative(`native binding not available: ${_state.initError}`);
959
- return _state.binding;
960
- };
961
- return {
962
- get: loadNativeParserBinding,
963
- reset: () => {
964
- _state.binding = void 0;
965
- _state.initError = null;
966
- }
967
- };
968
- };
969
- var nativeParserLoader = createNativeParserLoader();
970
- var DEFAULT_EXTENSIONS = [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"];
971
- var DEFAULT_IGNORES = ["node_modules", ".git", ".next", "dist", "out", ".turbo", ".cache"];
1938
+ }
972
1939
  function resolveScannerWorkerModulePath() {
973
1940
  const runtimeDir = (() => {
974
1941
  if (typeof __dirname !== "undefined" && __dirname.length > 0) {
975
1942
  return __dirname;
976
1943
  }
977
1944
  if (typeof import.meta !== "undefined" && import.meta.url) {
978
- return path3.dirname(fileURLToPath(import.meta.url));
1945
+ return path6__default.dirname(fileURLToPath(import.meta.url));
979
1946
  }
980
1947
  return process.cwd();
981
1948
  })();
982
1949
  const candidates = [
983
- path3.resolve(runtimeDir, "worker.cjs"),
984
- path3.resolve(runtimeDir, "worker.js"),
985
- path3.resolve(runtimeDir, "worker.ts")
1950
+ path6__default.resolve(runtimeDir, "worker.cjs"),
1951
+ path6__default.resolve(runtimeDir, "worker.js"),
1952
+ path6__default.resolve(runtimeDir, "worker.ts")
986
1953
  ];
987
1954
  for (const candidate of candidates) {
988
- if (fs.existsSync(candidate)) return candidate;
1955
+ if (fs4__default.existsSync(candidate)) return candidate;
989
1956
  }
990
1957
  return null;
991
1958
  }
@@ -995,7 +1962,7 @@ function scanWorkspaceInWorker(rootDir, options) {
995
1962
  if (!modulePath) {
996
1963
  return Promise.reject(new Error("scanner worker module path could not be resolved"));
997
1964
  }
998
- return new Promise((resolve, reject) => {
1965
+ return new Promise((resolve2, reject) => {
999
1966
  const settleState = { settled: false };
1000
1967
  const worker = new Worker(modulePath, { workerData: { rootDir, options: normalizedOptions } });
1001
1968
  const timeout = setTimeout(() => {
@@ -1015,7 +1982,7 @@ function scanWorkspaceInWorker(rootDir, options) {
1015
1982
  const message = parseScannerWorkerMessage(payload);
1016
1983
  finish(() => {
1017
1984
  if (message?.ok) {
1018
- resolve(parseScanWorkspaceResult(message.result));
1985
+ resolve2(parseScanWorkspaceResult(message.result));
1019
1986
  return;
1020
1987
  }
1021
1988
  reject(new Error(message?.error ?? "scanner worker failed without an error message"));
@@ -1042,19 +2009,19 @@ function collectCandidates(rootDir, ignoreDirectories, extensionSet) {
1042
2009
  if (!currentDir) continue;
1043
2010
  const entries = (() => {
1044
2011
  try {
1045
- return fs.readdirSync(currentDir, { withFileTypes: true });
2012
+ return fs4__default.readdirSync(currentDir, { withFileTypes: true });
1046
2013
  } catch {
1047
2014
  return [];
1048
2015
  }
1049
2016
  })();
1050
2017
  for (const entry of entries) {
1051
- const fullPath = path3.join(currentDir, entry.name);
2018
+ const fullPath = path6__default.join(currentDir, entry.name);
1052
2019
  if (entry.isDirectory()) {
1053
2020
  if (!ignoreDirectories.has(entry.name)) directories.push(fullPath);
1054
2021
  continue;
1055
2022
  }
1056
2023
  if (!entry.isFile()) continue;
1057
- if (!extensionSet.has(path3.extname(entry.name))) continue;
2024
+ if (!extensionSet.has(path6__default.extname(entry.name))) continue;
1058
2025
  candidates.push(fullPath);
1059
2026
  }
1060
2027
  }
@@ -1068,9 +2035,12 @@ function toCacheSize(size) {
1068
2035
  function scanSource(source) {
1069
2036
  const nativeBinding = nativeParserLoader.get();
1070
2037
  if (nativeBinding?.extractClassesFromSource) {
1071
- const classes = nativeBinding.extractClassesFromSource(source);
1072
- if (Array.isArray(classes)) {
1073
- return Array.from(new Set(classes.filter(Boolean)));
2038
+ const result = nativeBinding.extractClassesFromSource(source);
2039
+ if (Array.isArray(result)) {
2040
+ return Array.from(new Set(result.filter(Boolean)));
2041
+ }
2042
+ if (result !== null && result !== void 0 && Array.isArray(result.classes)) {
2043
+ return Array.from(new Set(result.classes.filter(Boolean)));
1074
2044
  }
1075
2045
  }
1076
2046
  throw new Error(
@@ -1078,15 +2048,18 @@ function scanSource(source) {
1078
2048
  );
1079
2049
  }
1080
2050
  function isScannableFile(filePath, includeExtensions = DEFAULT_EXTENSIONS) {
1081
- return includeExtensions.includes(path3.extname(filePath));
2051
+ return includeExtensions.includes(path6__default.extname(filePath));
1082
2052
  }
1083
2053
  function scanFile(filePath) {
1084
- const source = fs.readFileSync(filePath, "utf8");
1085
- const hash = hashContentNative(source) ?? void 0;
2054
+ const { scanFileNative: scanFileNative2 } = (init_native_bridge(), __toCommonJS(native_bridge_exports));
2055
+ const result = scanFileNative2(filePath);
2056
+ if (!result.ok) {
2057
+ throw new Error(`scanFile failed for ${filePath}: ${result.error ?? "unknown error"}`);
2058
+ }
1086
2059
  return {
1087
- file: filePath,
1088
- classes: scanSource(source),
1089
- ...hash ? { hash } : {}
2060
+ file: result.file,
2061
+ classes: result.classes,
2062
+ ...result.hash ? { hash: result.hash } : {}
1090
2063
  };
1091
2064
  }
1092
2065
  function scanWorkspace(rootDir, options = {}) {
@@ -1135,7 +2108,7 @@ function scanWorkspace(rootDir, options = {}) {
1135
2108
  for (const filePath of candidates) {
1136
2109
  const stat = (() => {
1137
2110
  try {
1138
- return fs.statSync(filePath);
2111
+ return fs4__default.statSync(filePath);
1139
2112
  } catch {
1140
2113
  return null;
1141
2114
  }
@@ -1161,7 +2134,7 @@ function scanWorkspace(rootDir, options = {}) {
1161
2134
  for (const { filePath, stat, size, cached } of ranked) {
1162
2135
  const content = (() => {
1163
2136
  try {
1164
- return fs.readFileSync(filePath, "utf8");
2137
+ return fs4__default.readFileSync(filePath, "utf8");
1165
2138
  } catch {
1166
2139
  return null;
1167
2140
  }
@@ -1223,18 +2196,245 @@ function scanWorkspace(rootDir, options = {}) {
1223
2196
  }
1224
2197
  async function scanWorkspaceAsync(rootDir, options = {}) {
1225
2198
  const normalizedOptions = parseScanWorkspaceOptions(options);
1226
- if (process.env.TWS_DISABLE_SCANNER_WORKER === "1") {
1227
- return scanWorkspace(rootDir, normalizedOptions);
2199
+ try {
2200
+ return await scanWorkspaceParallel(rootDir, {
2201
+ extensions: normalizedOptions.includeExtensions,
2202
+ ignoreDirs: normalizedOptions.ignoreDirectories
2203
+ });
2204
+ } catch (parallelError) {
2205
+ log3.debug(
2206
+ `parallel scan failed, retrying with single worker: ${parallelError instanceof Error ? parallelError.message : String(parallelError)}`
2207
+ );
1228
2208
  }
1229
2209
  try {
1230
2210
  return await scanWorkspaceInWorker(rootDir, normalizedOptions);
1231
2211
  } catch (error) {
1232
2212
  log3.debug(
1233
- `worker scan failed, falling back to sync scanner: ${error instanceof Error ? error.message : String(error)}`
2213
+ `worker scan failed, retrying with sync native scanner: ${error instanceof Error ? error.message : String(error)}`
1234
2214
  );
1235
2215
  return scanWorkspace(rootDir, normalizedOptions);
1236
2216
  }
1237
2217
  }
2218
+ var log3, SCAN_WORKER_TIMEOUT_MS, createNativeParserLoader, nativeParserLoader, DEFAULT_EXTENSIONS, DEFAULT_IGNORES;
2219
+ var init_src2 = __esm({
2220
+ "packages/domain/scanner/src/index.ts"() {
2221
+ init_src();
2222
+ init_cache_native();
2223
+ init_native_bridge();
2224
+ init_parallel_scanner();
2225
+ init_schemas();
2226
+ init_schemas();
2227
+ init_native_bridge();
2228
+ log3 = createLogger("scanner");
2229
+ SCAN_WORKER_TIMEOUT_MS = 12e4;
2230
+ createNativeParserLoader = () => {
2231
+ const _state = {
2232
+ binding: void 0,
2233
+ initError: null
2234
+ };
2235
+ const debugNative = (message) => {
2236
+ log3.debug(`[native] ${message}`);
2237
+ };
2238
+ const loadNativeParserBinding = () => {
2239
+ if (_state.binding !== void 0) return _state.binding;
2240
+ const runtimeDir = getRuntimeDir();
2241
+ const req = createRequire(path6__default.join(runtimeDir, "noop.cjs"));
2242
+ const candidates = [
2243
+ // ── binaryName baru: tailwind-styled-native (napi-rs naming) ──
2244
+ // cwd = repo root saat run dari root, atau package dir saat workspaces
2245
+ path6__default.resolve(process.cwd(), "native", "tailwind-styled-native.node"),
2246
+ path6__default.resolve(process.cwd(), "native", `tailwind-styled-native.${process.platform}-${process.arch}.node`),
2247
+ path6__default.resolve(process.cwd(), "native", `tailwind-styled-native.${process.platform}-${process.arch}-gnu.node`),
2248
+ // runtimeDir = dist/ → naik 4 level ke repo root
2249
+ path6__default.resolve(runtimeDir, "..", "..", "..", "..", "native", "tailwind-styled-native.node"),
2250
+ path6__default.resolve(runtimeDir, "..", "..", "..", "..", "native", `tailwind-styled-native.${process.platform}-${process.arch}-gnu.node`),
2251
+ // 3 level fallback (jika package di-nest lebih dangkal)
2252
+ path6__default.resolve(runtimeDir, "..", "..", "..", "native", "tailwind-styled-native.node"),
2253
+ path6__default.resolve(runtimeDir, "..", "..", "..", "native", `tailwind-styled-native.${process.platform}-${process.arch}-gnu.node`),
2254
+ // ── binaryName lama: tailwind_styled_parser (backward compat) ──
2255
+ path6__default.resolve(process.cwd(), "native/tailwind_styled_parser.node"),
2256
+ path6__default.resolve(process.cwd(), "native/build/Release/tailwind_styled_parser.node"),
2257
+ path6__default.resolve(runtimeDir, "..", "..", "..", "..", "native", "tailwind_styled_parser.node"),
2258
+ path6__default.resolve(runtimeDir, "..", "..", "..", "native", "tailwind_styled_parser.node"),
2259
+ path6__default.resolve(
2260
+ runtimeDir,
2261
+ "..",
2262
+ "..",
2263
+ "..",
2264
+ "native",
2265
+ "build",
2266
+ "Release",
2267
+ "tailwind_styled_parser.node"
2268
+ )
2269
+ ];
2270
+ for (const fullPath of candidates) {
2271
+ if (!fs4__default.existsSync(fullPath)) continue;
2272
+ try {
2273
+ const required = req(fullPath);
2274
+ if (required && (typeof required.extractClassesFromSource === "function" || typeof required.parseClasses === "function" || typeof required.parse_classes === "function")) {
2275
+ _state.binding = required;
2276
+ debugNative(`using native parser from ${fullPath}`);
2277
+ return _state.binding;
2278
+ }
2279
+ } catch (error) {
2280
+ _state.initError = error instanceof Error ? error.message : String(error);
2281
+ }
2282
+ }
2283
+ _state.binding = null;
2284
+ if (!_state.initError) {
2285
+ _state.initError = "native .node binding not found";
2286
+ }
2287
+ debugNative(`native binding not available: ${_state.initError}`);
2288
+ return _state.binding;
2289
+ };
2290
+ return {
2291
+ get: loadNativeParserBinding,
2292
+ reset: () => {
2293
+ _state.binding = void 0;
2294
+ _state.initError = null;
2295
+ }
2296
+ };
2297
+ };
2298
+ nativeParserLoader = createNativeParserLoader();
2299
+ DEFAULT_EXTENSIONS = [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"];
2300
+ DEFAULT_IGNORES = ["node_modules", ".git", ".next", "dist", "out", ".turbo", ".cache"];
2301
+ }
2302
+ });
2303
+
2304
+ // packages/domain/engine/src/native-bridge.ts
2305
+ function getDirname3() {
2306
+ if (typeof __dirname !== "undefined") return __dirname;
2307
+ if (typeof import.meta !== "undefined" && import.meta.url) {
2308
+ return getDirname(import.meta.url);
2309
+ }
2310
+ return process.cwd();
2311
+ }
2312
+ function getNativeEngineBinding() {
2313
+ return engineBindingLoader.get();
2314
+ }
2315
+ var log4, isValidEngineBinding, createEngineBindingLoader, engineBindingLoader;
2316
+ var init_native_bridge2 = __esm({
2317
+ "packages/domain/engine/src/native-bridge.ts"() {
2318
+ init_src();
2319
+ log4 = createDebugLogger("engine:native");
2320
+ isValidEngineBinding = (module) => {
2321
+ const candidate = module;
2322
+ return !!(candidate && (candidate.computeIncrementalDiff || candidate.processFileChange || candidate.hashFileContent));
2323
+ };
2324
+ createEngineBindingLoader = () => {
2325
+ const _state = {
2326
+ binding: void 0,
2327
+ loadError: null,
2328
+ candidatePaths: []
2329
+ };
2330
+ const throwNativeBindingError = () => {
2331
+ const lines = [
2332
+ "FATAL: Native engine binding not found.",
2333
+ "",
2334
+ "This package requires the Rust native binding 'tailwind_styled_parser.node'.",
2335
+ "The binding was not found in any of these paths:",
2336
+ ..._state.candidatePaths.map((p) => ` - ${p}`),
2337
+ ""
2338
+ ];
2339
+ if (_state.loadError) {
2340
+ lines.push("Load error:", ` ${_state.loadError}`, "");
2341
+ }
2342
+ lines.push(
2343
+ "To fix this, run:",
2344
+ " npm run build:rust",
2345
+ "",
2346
+ "This will build the native Rust module from the 'native/' directory.",
2347
+ "If you're using this package in a CI/CD environment, ensure Rust toolchain is installed",
2348
+ "and 'npm run build:rust' is executed before running tests or building."
2349
+ );
2350
+ throw new TwError("rust", "ENGINE_NATIVE_BINDING_NOT_FOUND", lines.join("\n"));
2351
+ };
2352
+ const getBinding = () => {
2353
+ const cached = _state.binding;
2354
+ if (cached !== void 0) {
2355
+ if (cached === null) {
2356
+ return throwNativeBindingError();
2357
+ }
2358
+ return cached;
2359
+ }
2360
+ const runtimeDir = getDirname3();
2361
+ const candidates = resolveNativeBindingCandidates({
2362
+ runtimeDir,
2363
+ includeDefaultCandidates: true
2364
+ });
2365
+ _state.candidatePaths = candidates;
2366
+ const { binding, loadErrors } = loadNativeBinding({
2367
+ runtimeDir,
2368
+ candidates,
2369
+ isValid: isValidEngineBinding,
2370
+ invalidExportMessage: "Module loaded but missing expected engine binding functions"
2371
+ });
2372
+ if (binding) {
2373
+ log4(`engine native binding loaded successfully`);
2374
+ _state.binding = binding;
2375
+ return binding;
2376
+ }
2377
+ if (loadErrors.length > 0) {
2378
+ _state.loadError = loadErrors.map((e) => `${e.path}: ${e.message}`).join("; ");
2379
+ }
2380
+ _state.binding = null;
2381
+ return throwNativeBindingError();
2382
+ };
2383
+ return {
2384
+ get: getBinding,
2385
+ reset: () => {
2386
+ _state.binding = void 0;
2387
+ _state.loadError = null;
2388
+ _state.candidatePaths = [];
2389
+ }
2390
+ };
2391
+ };
2392
+ engineBindingLoader = createEngineBindingLoader();
2393
+ }
2394
+ });
2395
+
2396
+ // packages/domain/compiler/src/index.ts
2397
+ init_nativeBridge();
2398
+ var transformSource = (source, opts) => {
2399
+ const native = getNativeBridge();
2400
+ if (!native?.transformSource) {
2401
+ throw new Error("FATAL: Native binding 'transformSource' is required but not available.");
2402
+ }
2403
+ const result = native.transformSource(source, opts);
2404
+ if (!result) {
2405
+ throw new Error("FATAL: transformSource returned null");
2406
+ }
2407
+ return result;
2408
+ };
2409
+ var generateCssForClasses = async (classes, _tailwindConfig, _root) => {
2410
+ const { runCssPipeline: runCssPipeline2 } = await Promise.resolve().then(() => (init_tailwindEngine(), tailwindEngine_exports));
2411
+ const result = await runCssPipeline2(classes);
2412
+ return result.css;
2413
+ };
2414
+ var mergeClassesStatic = (classes) => {
2415
+ const result = normalizeAndDedupClasses(classes);
2416
+ return result?.normalized || "";
2417
+ };
2418
+ var normalizeAndDedupClasses = (raw) => {
2419
+ const native = getNativeBridge();
2420
+ if (!native?.normalizeAndDedupClasses) {
2421
+ throw new Error("FATAL: Native binding 'normalizeAndDedupClasses' is required but not available.");
2422
+ }
2423
+ const result = native.normalizeAndDedupClasses(raw);
2424
+ return result || { normalized: "", duplicatesRemoved: 0, uniqueCount: 0 };
2425
+ };
2426
+ var runLoaderTransform = (ctx) => {
2427
+ const { filepath, source, options } = ctx;
2428
+ const result = transformSource(source, { filename: filepath, ...options });
2429
+ return {
2430
+ code: result?.code || "",
2431
+ changed: result?.changed || false,
2432
+ classes: result?.classes || []
2433
+ };
2434
+ };
2435
+
2436
+ // packages/domain/analyzer/src/analyzeWorkspace.ts
2437
+ init_src2();
1238
2438
 
1239
2439
  // packages/domain/analyzer/src/binding.ts
1240
2440
  init_src();
@@ -1244,7 +2444,7 @@ init_src();
1244
2444
  var DEFAULT_TOP_LIMIT = 10;
1245
2445
  var DEFAULT_FREQUENT_THRESHOLD = 2;
1246
2446
  var DEBUG_NAMESPACE = "tailwind-styled:analyzer";
1247
- function formatErrorMessage(error) {
2447
+ function formatErrorMessage2(error) {
1248
2448
  return error instanceof Error ? error.message : String(error);
1249
2449
  }
1250
2450
  function isRecord(value) {
@@ -1254,7 +2454,7 @@ function isRecord(value) {
1254
2454
  }
1255
2455
  async function pathExists(filePath) {
1256
2456
  try {
1257
- await fs.promises.access(filePath, fs.constants.F_OK);
2457
+ await fs4__default.promises.access(filePath, fs4__default.constants.F_OK);
1258
2458
  return true;
1259
2459
  } catch {
1260
2460
  return false;
@@ -1317,6 +2517,9 @@ var createAnalyzerBindingLoader = () => {
1317
2517
  };
1318
2518
  };
1319
2519
  var analyzerBindingLoader = createAnalyzerBindingLoader();
2520
+ async function getNativeBinding() {
2521
+ return analyzerBindingLoader.get();
2522
+ }
1320
2523
  async function requireNativeBinding() {
1321
2524
  const binding = await analyzerBindingLoader.get();
1322
2525
  if (binding?.analyzeClasses) return binding;
@@ -1350,7 +2553,7 @@ async function requireNativeBinding() {
1350
2553
 
1351
2554
  // packages/domain/analyzer/src/schemas.ts
1352
2555
  init_src();
1353
- var formatIssuePath3 = (path11) => path11.length > 0 ? path11.map(
2556
+ var formatIssuePath3 = (path13) => path13.length > 0 ? path13.map(
1354
2557
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
1355
2558
  ).join(".") : "<root>";
1356
2559
  var isPlainObject = (value) => {
@@ -1359,8 +2562,8 @@ var isPlainObject = (value) => {
1359
2562
  return proto === Object.prototype || proto === null;
1360
2563
  };
1361
2564
  var formatIssues2 = (error) => error.issues.map((issue) => {
1362
- const path11 = formatIssuePath3(issue.path);
1363
- return `${path11}: ${issue.message}`;
2565
+ const path13 = formatIssuePath3(issue.path);
2566
+ return `${path13}: ${issue.message}`;
1364
2567
  }).join("; ");
1365
2568
  var parseWithSchema2 = (schema, data, label) => {
1366
2569
  const parsed = schema.safeParse(data);
@@ -1449,183 +2652,29 @@ z.object({
1449
2652
  var parseAnalyzerOptions = (options) => parseWithSchema2(AnalyzerOptionsSchema, options ?? {}, "analyzeWorkspace options are invalid");
1450
2653
  var parseNativeReport = (report) => parseWithSchema2(NativeReportSchema, report, "Native analyzer report is invalid");
1451
2654
  var SUPPORTED_TAILWIND_CONFIG_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".js", ".cjs", ".mjs"]);
1452
- var KNOWN_UTILITY_PREFIXES = /* @__PURE__ */ new Set([
1453
- "absolute",
1454
- "align",
1455
- "animate",
1456
- "arbitrary",
1457
- "aspect",
1458
- "backdrop",
1459
- "basis",
1460
- "bg",
1461
- "block",
1462
- "border",
1463
- "bottom",
1464
- "col",
1465
- "container",
1466
- "contents",
1467
- "cursor",
1468
- "dark",
1469
- "display",
1470
- "divide",
1471
- "fill",
1472
- "fixed",
1473
- "flex",
1474
- "float",
1475
- "font",
1476
- "from",
1477
- "gap",
1478
- "grid",
1479
- "grow",
1480
- "h",
1481
- "hidden",
1482
- "inset",
1483
- "inline",
1484
- "isolate",
1485
- "items",
1486
- "justify",
1487
- "left",
1488
- "leading",
1489
- "line",
1490
- "list",
1491
- "m",
1492
- "max-h",
1493
- "max-w",
1494
- "mb",
1495
- "min-h",
1496
- "min-w",
1497
- "ml",
1498
- "mr",
1499
- "mt",
1500
- "mx",
1501
- "my",
1502
- "object",
1503
- "opacity",
1504
- "order",
1505
- "origin",
1506
- "outline",
1507
- "overflow",
1508
- "overscroll",
1509
- "p",
1510
- "pb",
1511
- "pe",
1512
- "perspective",
1513
- "place",
1514
- "pl",
1515
- "pointer",
1516
- "position",
1517
- "pr",
1518
- "ps",
1519
- "pt",
1520
- "px",
1521
- "py",
1522
- "relative",
1523
- "right",
1524
- "ring",
1525
- "rotate",
1526
- "rounded",
1527
- "row",
1528
- "scale",
1529
- "shadow",
1530
- "shrink",
1531
- "size",
1532
- "skew",
1533
- "snap",
1534
- "space-x",
1535
- "space-y",
1536
- "sr",
1537
- "start",
1538
- "static",
1539
- "sticky",
1540
- "stroke",
1541
- "table",
1542
- "text",
1543
- "to",
1544
- "top",
1545
- "touch",
1546
- "tracking",
1547
- "transform",
1548
- "transition",
1549
- "translate",
1550
- "truncate",
1551
- "underline",
1552
- "via",
1553
- "visible",
1554
- "w",
1555
- "whitespace",
1556
- "z"
1557
- ]);
1558
2655
  var tailwindConfigCache = /* @__PURE__ */ new Map();
1559
- var splitVariantAndBase = (className) => {
1560
- const parts = className.split(":");
1561
- if (parts.length <= 1) return { variantKey: "", base: className };
1562
- const base = parts.pop() ?? className;
1563
- return { variantKey: parts.join(":"), base };
1564
- };
1565
- var isArbitraryUtility = (baseClass) => {
1566
- return baseClass.includes("[") && baseClass.includes("]");
1567
- };
1568
- var resolveConflictGroup = (base) => {
1569
- if (isArbitraryUtility(base)) return null;
1570
- if (["block", "inline", "inline-block", "inline-flex", "flex", "grid", "hidden"].includes(base))
1571
- return "display";
1572
- if (base.startsWith("bg-")) return "bg";
1573
- if (base.startsWith("text-")) return "text";
1574
- if (base.startsWith("font-")) return "font";
1575
- if (base.startsWith("rounded")) return "rounded";
1576
- if (base.startsWith("shadow")) return "shadow";
1577
- if (base.startsWith("border-")) return "border";
1578
- if (base.startsWith("opacity-")) return "opacity";
1579
- if (base.startsWith("w-") || base.startsWith("min-w-") || base.startsWith("max-w-"))
1580
- return "width";
1581
- if (base.startsWith("h-") || base.startsWith("min-h-") || base.startsWith("max-h-"))
1582
- return "height";
1583
- if (base.startsWith("p-") || base.startsWith("px-") || base.startsWith("py-")) return "padding";
1584
- if (base.startsWith("m-") || base.startsWith("mx-") || base.startsWith("my-")) return "margin";
1585
- return null;
1586
- };
1587
- var detectConflicts = (usages) => {
1588
- const buckets = /* @__PURE__ */ new Map();
1589
- for (const usage of usages) {
1590
- const { variantKey, base } = splitVariantAndBase(usage.name);
1591
- const group = resolveConflictGroup(base);
1592
- if (!group) continue;
1593
- const key = `${variantKey}::${group}`;
1594
- const bucket = buckets.get(key) ?? {
1595
- variantKey,
1596
- group,
1597
- classes: /* @__PURE__ */ new Set()
1598
- };
1599
- bucket.classes.add(usage.name);
1600
- buckets.set(key, bucket);
1601
- }
1602
- const conflicts = [];
1603
- const conflictedClassNames = /* @__PURE__ */ new Set();
1604
- for (const bucket of buckets.values()) {
1605
- if (bucket.classes.size <= 1) continue;
1606
- const classes = Array.from(bucket.classes).sort();
1607
- for (const className of classes) conflictedClassNames.add(className);
1608
- const variantLabel = bucket.variantKey.length > 0 ? bucket.variantKey : "base";
1609
- conflicts.push({
1610
- className: bucket.group,
1611
- variants: bucket.variantKey.length > 0 ? bucket.variantKey.split(":") : [],
1612
- classes,
1613
- message: `Multiple ${bucket.group} utilities detected for "${variantLabel}".`
1614
- });
2656
+ var detectConflicts = async (usages) => {
2657
+ const native = await getNativeBinding();
2658
+ if (!native?.detectClassConflicts) {
2659
+ throw new Error("FATAL: Native binding 'detectClassConflicts' is required but not available.");
1615
2660
  }
1616
- conflicts.sort((left, right) => {
1617
- if (right.classes.length !== left.classes.length)
1618
- return right.classes.length - left.classes.length;
1619
- return left.className.localeCompare(right.className);
1620
- });
1621
- return { conflicts, conflictedClassNames };
2661
+ const result = native.detectClassConflicts(JSON.stringify(usages.map((u) => ({ name: u.name, count: u.count }))));
2662
+ return {
2663
+ conflicts: result.conflicts.map((c) => ({
2664
+ className: c.group,
2665
+ variants: c.variantKey.length > 0 ? c.variantKey.split(":") : [],
2666
+ classes: c.classes,
2667
+ message: c.message
2668
+ })),
2669
+ conflictedClassNames: new Set(result.conflictedClassNames)
2670
+ };
1622
2671
  };
1623
2672
  var isSupportedTailwindConfigPath = (configPath) => {
1624
- return SUPPORTED_TAILWIND_CONFIG_EXTENSIONS.has(path3.extname(configPath).toLowerCase());
2673
+ return SUPPORTED_TAILWIND_CONFIG_EXTENSIONS.has(path6__default.extname(configPath).toLowerCase());
1625
2674
  };
1626
2675
  var resolveTailwindConfigPath = async (root, explicitPath) => {
1627
2676
  if (explicitPath) {
1628
- const resolved = path3.resolve(root, explicitPath);
2677
+ const resolved = path6__default.resolve(root, explicitPath);
1629
2678
  if (!await pathExists(resolved)) return null;
1630
2679
  return resolved;
1631
2680
  }
@@ -1636,7 +2685,7 @@ var resolveTailwindConfigPath = async (root, explicitPath) => {
1636
2685
  "tailwind.config.mjs"
1637
2686
  ];
1638
2687
  for (const candidate of candidates) {
1639
- const fullPath = path3.resolve(root, candidate);
2688
+ const fullPath = path6__default.resolve(root, candidate);
1640
2689
  if (await pathExists(fullPath)) return fullPath;
1641
2690
  }
1642
2691
  return null;
@@ -1690,15 +2739,19 @@ var collectCustomUtilities = (config) => {
1690
2739
  return out;
1691
2740
  };
1692
2741
  var collectSafelistFromSource = async (configPath) => {
1693
- const source = await fs.promises.readFile(configPath, "utf8");
1694
- const safelistBlock = source.match(/safelist\s*:\s*\[([\s\S]*?)\]/m)?.[1];
1695
- if (!safelistBlock) return [];
1696
- const out = /* @__PURE__ */ new Set();
1697
- for (const token of safelistBlock.matchAll(/["'`]([^"'`]+)["'`]/g)) {
2742
+ const source = await fs4__default.promises.readFile(configPath, "utf8");
2743
+ const { extractClassesNative: extractClassesNative2 } = await Promise.resolve().then(() => (init_src2(), src_exports2));
2744
+ const allTokens = extractClassesNative2(source);
2745
+ const hasSafelist = source.includes("safelist");
2746
+ if (!hasSafelist) return [];
2747
+ const safelistMatch = source.match(/safelist\s*:\s*\[([\s\S]*?)\]/m)?.[1];
2748
+ if (!safelistMatch) return [];
2749
+ const safelistSet = /* @__PURE__ */ new Set();
2750
+ for (const token of safelistMatch.matchAll(/["'`]([^"'`]+)["'`]/g)) {
1698
2751
  const value = token[1].trim();
1699
- if (value.length > 0) out.add(value);
2752
+ if (value.length > 0) safelistSet.add(value);
1700
2753
  }
1701
- return Array.from(out);
2754
+ return allTokens.filter((t) => safelistSet.has(t));
1702
2755
  };
1703
2756
  var loadTailwindConfig = async (root, semanticOption) => {
1704
2757
  const startMs = Date.now();
@@ -1713,7 +2766,7 @@ var loadTailwindConfig = async (root, semanticOption) => {
1713
2766
  customUtilities: /* @__PURE__ */ new Set()
1714
2767
  };
1715
2768
  }
1716
- const configStat = await fs.promises.stat(configPath).catch(() => null);
2769
+ const configStat = await fs4__default.promises.stat(configPath).catch(() => null);
1717
2770
  if (configStat) {
1718
2771
  const cached = tailwindConfigCache.get(configPath);
1719
2772
  if (cached && cached.mtimeMs === configStat.mtimeMs && cached.size === configStat.size) {
@@ -1742,7 +2795,7 @@ var loadTailwindConfig = async (root, semanticOption) => {
1742
2795
  warning: "Tailwind config export must be an object or a function returning an object."
1743
2796
  };
1744
2797
  } catch (error) {
1745
- return { config: null, warning: formatErrorMessage(error) };
2798
+ return { config: null, warning: formatErrorMessage2(error) };
1746
2799
  }
1747
2800
  })();
1748
2801
  const { config, warning } = result;
@@ -1757,7 +2810,7 @@ var loadTailwindConfig = async (root, semanticOption) => {
1757
2810
  for (const item of await collectSafelistFromSource(configPath)) safelist.add(item);
1758
2811
  } catch (error) {
1759
2812
  debugLog(
1760
- `failed to parse safelist from source at "${configPath}": ${formatErrorMessage(error)}`
2813
+ `failed to parse safelist from source at "${configPath}": ${formatErrorMessage2(error)}`
1761
2814
  );
1762
2815
  }
1763
2816
  }
@@ -1780,40 +2833,27 @@ var loadTailwindConfig = async (root, semanticOption) => {
1780
2833
  );
1781
2834
  return loaded;
1782
2835
  };
1783
- var utilityPrefix = (baseClass) => {
1784
- const normalized = baseClass.startsWith("-") ? baseClass.slice(1) : baseClass;
1785
- if (normalized.includes("[") && normalized.includes("]")) return "arbitrary";
1786
- if (normalized.startsWith("min-w-")) return "min-w";
1787
- if (normalized.startsWith("max-w-")) return "max-w";
1788
- if (normalized.startsWith("min-h-")) return "min-h";
1789
- if (normalized.startsWith("max-h-")) return "max-h";
1790
- if (normalized.startsWith("space-x-")) return "space-x";
1791
- if (normalized.startsWith("space-y-")) return "space-y";
1792
- if (normalized.startsWith("inline-")) return "inline";
1793
- if (normalized.startsWith("border-")) return "border";
1794
- if (normalized.startsWith("text-")) return "text";
1795
- if (normalized.startsWith("bg-")) return "bg";
1796
- if (normalized.startsWith("rounded")) return "rounded";
1797
- if (normalized.startsWith("shadow")) return "shadow";
1798
- const hyphen = normalized.indexOf("-");
1799
- if (hyphen < 0) return normalized;
1800
- return normalized.slice(0, hyphen);
1801
- };
1802
- var isKnownTailwindClass = (className, safelist, customUtilities) => {
1803
- if (safelist.has(className) || customUtilities.has(className)) return true;
1804
- const { base } = splitVariantAndBase(className);
1805
- if (customUtilities.has(base)) return true;
1806
- const prefix = utilityPrefix(base);
1807
- return KNOWN_UTILITY_PREFIXES.has(prefix);
1808
- };
1809
2836
  var buildSemanticReport = async (usages, root, semanticOption) => {
1810
2837
  const loadedConfig = await loadTailwindConfig(root, semanticOption);
1811
2838
  const safelist = loadedConfig?.safelist ?? /* @__PURE__ */ new Set();
1812
2839
  const customUtilities = loadedConfig?.customUtilities ?? /* @__PURE__ */ new Set();
1813
2840
  const usageNames = new Set(usages.map((usage) => usage.name));
1814
2841
  const unusedClasses = Array.from(safelist).filter((className) => !usageNames.has(className)).sort().map((className) => ({ name: className, count: 0, isUnused: true }));
1815
- const unknownClasses = usages.filter((usage) => !isKnownTailwindClass(usage.name, safelist, customUtilities)).map((usage) => ({ ...usage, isUnused: true }));
1816
- const { conflicts } = detectConflicts(usages);
2842
+ const native = await getNativeBinding();
2843
+ if (!native?.classifyKnownClasses) {
2844
+ throw new Error("FATAL: Native binding 'classifyKnownClasses' is required but not available.");
2845
+ }
2846
+ const classNames = usages.map((u) => u.name);
2847
+ const results = native.classifyKnownClasses(
2848
+ classNames,
2849
+ Array.from(safelist),
2850
+ Array.from(customUtilities)
2851
+ );
2852
+ const unknownSet = new Set(
2853
+ results.filter((r) => !r.isKnown).map((r) => r.className)
2854
+ );
2855
+ const unknownClasses = usages.filter((usage) => unknownSet.has(usage.name)).map((usage) => ({ ...usage, isUnused: true }));
2856
+ const { conflicts } = await detectConflicts(usages);
1817
2857
  return {
1818
2858
  unusedClasses,
1819
2859
  unknownClasses,
@@ -1849,13 +2889,17 @@ function normalizeScan(scan, includeClass) {
1849
2889
  uniqueClasses: Array.from(unique).sort()
1850
2890
  };
1851
2891
  }
1852
- function collectClassCounts(scan) {
1853
- const counts = /* @__PURE__ */ new Map();
1854
- for (const file of scan.files) {
1855
- for (const className of file.classes) {
1856
- counts.set(className, (counts.get(className) ?? 0) + 1);
1857
- }
2892
+ async function collectClassCounts(scan) {
2893
+ const native = await requireNativeBinding();
2894
+ if (!native?.collectClassCounts) {
2895
+ throw new Error("FATAL: Native binding 'collectClassCounts' is required but not available.");
1858
2896
  }
2897
+ const filesJson = JSON.stringify(
2898
+ scan.files.map((f) => ({ file: f.file ?? "", classes: f.classes }))
2899
+ );
2900
+ const result = native.collectClassCounts(filesJson);
2901
+ const counts = /* @__PURE__ */ new Map();
2902
+ for (const entry of result) counts.set(entry.name, entry.count);
1859
2903
  return counts;
1860
2904
  }
1861
2905
  function buildClassUsage(counts) {
@@ -1864,29 +2908,24 @@ function buildClassUsage(counts) {
1864
2908
  return left.name.localeCompare(right.name);
1865
2909
  });
1866
2910
  }
1867
- function buildDistribution(usages) {
1868
- const distribution = {
1869
- "1": 0,
1870
- "2-3": 0,
1871
- "4-7": 0,
1872
- "8+": 0
1873
- };
1874
- for (const usage of usages) {
1875
- if (usage.count === 1) {
1876
- distribution["1"] += 1;
1877
- } else if (usage.count <= 3) {
1878
- distribution["2-3"] += 1;
1879
- } else if (usage.count <= 7) {
1880
- distribution["4-7"] += 1;
1881
- } else {
1882
- distribution["8+"] += 1;
1883
- }
2911
+ async function buildDistribution(usages, native) {
2912
+ const binding = native ?? await requireNativeBinding();
2913
+ if (!binding?.buildDistribution) {
2914
+ throw new Error("FATAL: Native binding 'buildDistribution' is required but not available.");
1884
2915
  }
1885
- return distribution;
2916
+ const result = binding.buildDistribution(
2917
+ JSON.stringify(usages.map((u) => ({ name: u.name, count: u.count })))
2918
+ );
2919
+ return {
2920
+ "1": result.once,
2921
+ "2-3": result.few,
2922
+ "4-7": result.moderate,
2923
+ "8+": result.frequent
2924
+ };
1886
2925
  }
1887
2926
  async function analyzeWorkspace(root, options = {}) {
1888
2927
  const startedAtMs = Date.now();
1889
- const resolvedRoot = path3.resolve(root);
2928
+ const resolvedRoot = path6__default.resolve(root);
1890
2929
  const normalizedOptions = parseAnalyzerOptions(options);
1891
2930
  const scan = await (async () => {
1892
2931
  const scanStartedAtMs = Date.now();
@@ -1898,7 +2937,7 @@ async function analyzeWorkspace(root, options = {}) {
1898
2937
  return result;
1899
2938
  } catch (error) {
1900
2939
  throw new Error(
1901
- `Failed to scan workspace at "${resolvedRoot}": ${formatErrorMessage(error)}`,
2940
+ `Failed to scan workspace at "${resolvedRoot}": ${formatErrorMessage2(error)}`,
1902
2941
  {
1903
2942
  cause: error
1904
2943
  }
@@ -1923,14 +2962,14 @@ async function analyzeWorkspace(root, options = {}) {
1923
2962
  return parseNativeReport(report);
1924
2963
  } catch (error) {
1925
2964
  throw new Error(
1926
- `Native analyzer failed for "${resolvedRoot}": ${formatErrorMessage(error)}`,
2965
+ `Native analyzer failed for "${resolvedRoot}": ${formatErrorMessage2(error)}`,
1927
2966
  {
1928
2967
  cause: error
1929
2968
  }
1930
2969
  );
1931
2970
  }
1932
2971
  })();
1933
- const counts = collectClassCounts(normalizedScan);
2972
+ const counts = await collectClassCounts(normalizedScan);
1934
2973
  const baseAll = buildClassUsage(counts);
1935
2974
  const { all, semanticReport } = await (async () => {
1936
2975
  if (!normalizedOptions.semantic) {
@@ -1951,18 +2990,24 @@ async function analyzeWorkspace(root, options = {}) {
1951
2990
  return { all: updatedAll, semanticReport: report };
1952
2991
  } catch (error) {
1953
2992
  throw new Error(
1954
- `Failed to build semantic report for "${resolvedRoot}": ${formatErrorMessage(error)}`,
2993
+ `Failed to build semantic report for "${resolvedRoot}": ${formatErrorMessage2(error)}`,
1955
2994
  { cause: error }
1956
2995
  );
1957
2996
  }
1958
2997
  })();
1959
- const top = all.slice(0, topLimit);
1960
- const frequent = all.filter((usage) => usage.count >= frequentThreshold).slice(0, topLimit);
1961
- const unique = all.filter((usage) => usage.count === 1);
1962
- const totalClassOccurrences = all.reduce((sum, usage) => sum + usage.count, 0);
2998
+ const classStatsNative = binding?.computeClassStats?.(
2999
+ JSON.stringify(all),
3000
+ topLimit,
3001
+ frequentThreshold
3002
+ );
3003
+ const top = classStatsNative ? JSON.parse(classStatsNative.topJson) : all.slice(0, topLimit);
3004
+ const frequent = classStatsNative ? JSON.parse(classStatsNative.frequentJson) : all.filter((usage) => usage.count >= frequentThreshold).slice(0, topLimit);
3005
+ const unique = classStatsNative ? JSON.parse(classStatsNative.uniqueJson) : all.filter((usage) => usage.count === 1);
3006
+ const totalClassOccurrences = classStatsNative ? classStatsNative.totalClassOccurrences : all.reduce((sum, usage) => sum + usage.count, 0);
1963
3007
  debugLog(
1964
3008
  `analyzeWorkspace completed in ${Date.now() - startedAtMs}ms (files=${normalizedScan.totalFiles}, uniqueClasses=${all.length})`
1965
3009
  );
3010
+ const distribution = await buildDistribution(all, binding);
1966
3011
  return {
1967
3012
  root: nativeReport.root || resolvedRoot,
1968
3013
  totalFiles: nativeReport.totalFiles,
@@ -1973,138 +3018,57 @@ async function analyzeWorkspace(root, options = {}) {
1973
3018
  top,
1974
3019
  frequent,
1975
3020
  unique,
1976
- distribution: buildDistribution(all)
3021
+ distribution
1977
3022
  },
3023
+ // topClasses — alias for classStats.top (test contract & backward compat)
3024
+ topClasses: top,
1978
3025
  safelist: all.map((usage) => usage.name),
1979
3026
  ...semanticReport ? { semantic: semanticReport } : {}
1980
3027
  };
1981
3028
  }
1982
3029
 
1983
3030
  // packages/domain/engine/src/index.ts
3031
+ init_src2();
1984
3032
  init_src();
1985
- init_src();
1986
-
1987
- // packages/domain/engine/src/native-bridge.ts
1988
- init_src();
1989
- var log4 = createDebugLogger("engine:native");
1990
- function getDirname3() {
1991
- if (typeof __dirname !== "undefined") return __dirname;
1992
- if (typeof import.meta !== "undefined" && import.meta.url) {
1993
- return getDirname(import.meta.url);
1994
- }
1995
- return process.cwd();
1996
- }
1997
- var isValidEngineBinding = (module) => {
1998
- const candidate = module;
1999
- return !!(candidate && (candidate.computeIncrementalDiff || candidate.processFileChange || candidate.hashFileContent));
2000
- };
2001
- var createEngineBindingLoader = () => {
2002
- const _state = {
2003
- binding: void 0,
2004
- loadError: null,
2005
- candidatePaths: []
2006
- };
2007
- const throwNativeBindingError = () => {
2008
- const lines = [
2009
- "FATAL: Native engine binding not found.",
2010
- "",
2011
- "This package requires the Rust native binding 'tailwind_styled_parser.node'.",
2012
- "The binding was not found in any of these paths:",
2013
- ..._state.candidatePaths.map((p) => ` - ${p}`),
2014
- ""
2015
- ];
2016
- if (_state.loadError) {
2017
- lines.push("Load error:", ` ${_state.loadError}`, "");
2018
- }
2019
- lines.push(
2020
- "To fix this, run:",
2021
- " npm run build:rust",
2022
- "",
2023
- "This will build the native Rust module from the 'native/' directory.",
2024
- "If you're using this package in a CI/CD environment, ensure Rust toolchain is installed",
2025
- "and 'npm run build:rust' is executed before running tests or building."
2026
- );
2027
- throw new TwError("rust", "ENGINE_NATIVE_BINDING_NOT_FOUND", lines.join("\n"));
2028
- };
2029
- const getBinding = () => {
2030
- const cached = _state.binding;
2031
- if (cached !== void 0) {
2032
- if (cached === null) {
2033
- return throwNativeBindingError();
2034
- }
2035
- return cached;
2036
- }
2037
- const runtimeDir = getDirname3();
2038
- const candidates = resolveNativeBindingCandidates({
2039
- runtimeDir,
2040
- includeDefaultCandidates: true
2041
- });
2042
- _state.candidatePaths = candidates;
2043
- const { binding, loadErrors } = loadNativeBinding({
2044
- runtimeDir,
2045
- candidates,
2046
- isValid: isValidEngineBinding,
2047
- invalidExportMessage: "Module loaded but missing expected engine binding functions"
2048
- });
2049
- if (binding) {
2050
- log4(`engine native binding loaded successfully`);
2051
- _state.binding = binding;
2052
- return binding;
2053
- }
2054
- if (loadErrors.length > 0) {
2055
- _state.loadError = loadErrors.map((e) => `${e.path}: ${e.message}`).join("; ");
2056
- }
2057
- _state.binding = null;
2058
- return throwNativeBindingError();
2059
- };
2060
- return {
2061
- get: getBinding,
2062
- reset: () => {
2063
- _state.binding = void 0;
2064
- _state.loadError = null;
2065
- _state.candidatePaths = [];
2066
- }
2067
- };
2068
- };
2069
- var engineBindingLoader = createEngineBindingLoader();
2070
- function getNativeEngineBinding() {
2071
- return engineBindingLoader.get();
2072
- }
2073
3033
 
2074
3034
  // packages/domain/engine/src/incremental.ts
3035
+ init_src2();
3036
+ init_src();
3037
+ init_native_bridge2();
2075
3038
  var DEFAULT_EXTENSIONS2 = [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"];
2076
3039
  var log5 = createLogger("engine:incremental");
2077
3040
  function rebuildWorkspaceResult(byFile) {
2078
3041
  const files = Array.from(byFile.values());
2079
- const unique = /* @__PURE__ */ new Set();
2080
- for (const file of files) {
2081
- for (const cls of file.classes) unique.add(cls);
3042
+ const native = getNativeEngineBinding();
3043
+ if (native?.rebuildWorkspaceResult) {
3044
+ const result = native.rebuildWorkspaceResult(files);
3045
+ return {
3046
+ files: result.files,
3047
+ totalFiles: result.totalFiles,
3048
+ uniqueClasses: result.uniqueClasses
3049
+ };
2082
3050
  }
2083
- return {
2084
- files,
2085
- totalFiles: files.length,
2086
- uniqueClasses: Array.from(unique).sort()
2087
- };
3051
+ throw new Error("FATAL: Native binding 'rebuildWorkspaceResult' is required but not available.");
2088
3052
  }
2089
3053
  function applyClassDiff(existing, added, removed) {
2090
- const next = new Set(existing);
2091
- for (const cls of added) next.add(cls);
2092
- for (const cls of removed) next.delete(cls);
2093
- return Array.from(next);
3054
+ const native = getNativeEngineBinding();
3055
+ if (native?.applyClassDiff) {
3056
+ return native.applyClassDiff(existing, added, removed);
3057
+ }
3058
+ throw new Error("FATAL: Native binding 'applyClassDiff' is required but not available.");
2094
3059
  }
2095
3060
  function areClassSetsEqual(a, b) {
2096
- if (a.length !== b.length) return false;
2097
- const bSet = new Set(b);
2098
- for (const cls of a) {
2099
- if (!bSet.has(cls)) return false;
3061
+ const native = getNativeEngineBinding();
3062
+ if (native?.areClassSetsEqual) {
3063
+ return native.areClassSetsEqual(a, b);
2100
3064
  }
2101
- return true;
3065
+ throw new Error("FATAL: Native binding 'areClassSetsEqual' is required but not available.");
2102
3066
  }
2103
3067
  function applyIncrementalChange(previous, filePath, type, scanner) {
2104
3068
  const includeExtensions = scanner?.includeExtensions ?? DEFAULT_EXTENSIONS2;
2105
3069
  if (!isScannableFile(filePath, includeExtensions)) return previous;
2106
- const byFile = new Map(previous.files.map((f) => [path3.resolve(f.file), f]));
2107
- const normalizedPath = path3.resolve(filePath);
3070
+ const byFile = new Map(previous.files.map((f) => [path6__default.resolve(f.file), f]));
3071
+ const normalizedPath = path6__default.resolve(filePath);
2108
3072
  const native = getNativeEngineBinding();
2109
3073
  if (!native?.processFileChange) {
2110
3074
  throw new Error(
@@ -2120,7 +3084,7 @@ function applyIncrementalChange(previous, filePath, type, scanner) {
2120
3084
  }
2121
3085
  log5.debug(`native change ${normalizedPath}`);
2122
3086
  const scanned = scanFile(normalizedPath);
2123
- const content = fs.readFileSync(normalizedPath, "utf8");
3087
+ const content = fs4__default.readFileSync(normalizedPath, "utf8");
2124
3088
  const diff = native.processFileChange(normalizedPath, scanned.classes, content);
2125
3089
  const existing = byFile.get(normalizedPath);
2126
3090
  if (diff && existing) {
@@ -2189,8 +3153,8 @@ var METRICS_FILE_NAME = "metrics.json";
2189
3153
  var CACHE_DIR = ".tw-cache";
2190
3154
  function writeMetrics(metrics, cwd = process.cwd()) {
2191
3155
  try {
2192
- const cacheDir = path3.join(cwd, CACHE_DIR);
2193
- fs.mkdirSync(cacheDir, { recursive: true });
3156
+ const cacheDir = path6__default.join(cwd, CACHE_DIR);
3157
+ fs4__default.mkdirSync(cacheDir, { recursive: true });
2194
3158
  const mem = process.memoryUsage();
2195
3159
  const data = {
2196
3160
  ...metrics,
@@ -2201,7 +3165,7 @@ function writeMetrics(metrics, cwd = process.cwd()) {
2201
3165
  },
2202
3166
  generatedAt: (/* @__PURE__ */ new Date()).toISOString()
2203
3167
  };
2204
- fs.writeFileSync(path3.join(cacheDir, METRICS_FILE_NAME), JSON.stringify(data, null, 2));
3168
+ fs4__default.writeFileSync(path6__default.join(cacheDir, METRICS_FILE_NAME), JSON.stringify(data, null, 2));
2205
3169
  } catch {
2206
3170
  }
2207
3171
  }
@@ -2306,96 +3270,78 @@ z.object({
2306
3270
  });
2307
3271
  var parseEngineOptions = (options) => parseWithSchema3(EngineOptionsSchema, options ?? {}, "engine options are invalid");
2308
3272
  var parseEngineWatchOptions = (options) => parseWithSchema3(EngineWatchOptionsSchema, options ?? {}, "engine watch options are invalid");
2309
- var DEFAULT_IGNORES2 = ["node_modules", ".git", ".next", "dist", "out", ".turbo", ".cache"];
2310
- function watchWorkspace(rootDir, onEvent, options = {}) {
2311
- const ignoreDirectories = new Set(options.ignoreDirectories ?? DEFAULT_IGNORES2);
2312
- const watchers = /* @__PURE__ */ new Map();
2313
- const restartTimers = /* @__PURE__ */ new Map();
2314
- const debounceMs = options.debounceMs ?? 100;
3273
+
3274
+ // packages/domain/engine/src/watch.ts
3275
+ var _native = null;
3276
+ function getNativeWatcher() {
3277
+ if (_native !== null) return _native;
3278
+ try {
3279
+ const { resolveNativeBinary: resolveNativeBinary2 } = (init_src(), __toCommonJS(src_exports));
3280
+ const { path: binPath } = resolveNativeBinary2(__dirname);
3281
+ if (binPath) {
3282
+ _native = __require(binPath);
3283
+ }
3284
+ } catch {
3285
+ _native = {};
3286
+ }
3287
+ return _native;
3288
+ }
3289
+ function watchWorkspaceNative(rootDir, onEvent, options) {
3290
+ const native = getNativeWatcher();
3291
+ if (!native?.startWatch || !native?.pollWatchEvents || !native?.stopWatch) {
3292
+ return null;
3293
+ }
3294
+ const result = native.startWatch(rootDir);
3295
+ if (!result || result.status !== "ok") {
3296
+ return null;
3297
+ }
3298
+ const { handleId } = result;
3299
+ const pollMs = options.pollIntervalMs ?? 200;
2315
3300
  const pending = /* @__PURE__ */ new Map();
2316
- const shouldIgnore = (targetPath) => {
2317
- const parts = targetPath.split(path3.sep);
2318
- return parts.some((part) => ignoreDirectories.has(part));
2319
- };
2320
- const enqueue = (event) => {
3301
+ const debounceMs = options.debounceMs ?? 100;
3302
+ function enqueue(event) {
2321
3303
  const key = `${event.type}:${event.filePath}`;
2322
3304
  const existing = pending.get(key);
2323
- if (existing) clearTimeout(existing);
3305
+ if (existing) clearTimeout(existing.timer);
2324
3306
  const timer = setTimeout(() => {
2325
3307
  pending.delete(key);
2326
3308
  onEvent(event);
2327
3309
  }, debounceMs);
2328
- pending.set(key, timer);
2329
- };
2330
- const safeUnwatch = (dir) => {
2331
- const watcher = watchers.get(dir);
2332
- if (!watcher) return;
2333
- try {
2334
- watcher.close();
2335
- } catch {
2336
- }
2337
- watchers.delete(dir);
2338
- };
2339
- const scheduleRestart = (dir) => {
2340
- const previous = restartTimers.get(dir);
2341
- if (previous) clearTimeout(previous);
2342
- const timer = setTimeout(() => {
2343
- restartTimers.delete(dir);
2344
- watchDir(dir);
2345
- }, 250);
2346
- restartTimers.set(dir, timer);
2347
- };
2348
- const watchDir = (dir) => {
2349
- if (watchers.has(dir) || shouldIgnore(dir) || !fs.existsSync(dir)) return;
3310
+ pending.set(key, { event, timer });
3311
+ }
3312
+ const intervalId = setInterval(() => {
2350
3313
  try {
2351
- const stat = fs.lstatSync(dir);
2352
- if (!stat.isDirectory() || stat.isSymbolicLink()) return;
2353
- } catch {
2354
- return;
2355
- }
2356
- const watcher = fs.watch(dir, { persistent: true }, (_eventType, fileName) => {
2357
- if (!fileName) return;
2358
- const fullPath = path3.join(dir, fileName.toString());
2359
- if (shouldIgnore(fullPath)) return;
2360
- if (fs.existsSync(fullPath)) {
2361
- try {
2362
- const stat = fs.lstatSync(fullPath);
2363
- if (stat.isSymbolicLink()) return;
2364
- if (stat.isDirectory()) {
2365
- watchDir(fullPath);
2366
- return;
2367
- }
2368
- enqueue({ type: "change", filePath: fullPath });
2369
- return;
2370
- } catch {
2371
- }
3314
+ const events = native.pollWatchEvents(handleId);
3315
+ for (const ev of events) {
3316
+ const type = ev.kind === "unlink" ? "unlink" : "change";
3317
+ enqueue({ type, filePath: ev.path });
2372
3318
  }
2373
- enqueue({ type: "unlink", filePath: fullPath });
2374
- });
2375
- watcher.on("error", (error) => {
2376
- safeUnwatch(dir);
2377
- const watcherError = error instanceof Error ? error : new Error(String(error));
2378
- options.onError?.(watcherError, dir);
2379
- scheduleRestart(dir);
2380
- });
2381
- watchers.set(dir, watcher);
2382
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
2383
- if (!entry.isDirectory()) continue;
2384
- watchDir(path3.join(dir, entry.name));
3319
+ } catch (err) {
3320
+ options.onError?.(
3321
+ err instanceof Error ? err : new Error(String(err)),
3322
+ rootDir
3323
+ );
2385
3324
  }
2386
- };
2387
- watchDir(path3.resolve(rootDir));
3325
+ }, pollMs);
2388
3326
  return {
2389
3327
  close() {
2390
- for (const timer of pending.values()) clearTimeout(timer);
3328
+ clearInterval(intervalId);
3329
+ for (const { timer } of pending.values()) clearTimeout(timer);
2391
3330
  pending.clear();
2392
- for (const timer of restartTimers.values()) clearTimeout(timer);
2393
- restartTimers.clear();
2394
- for (const watcher of watchers.values()) watcher.close();
2395
- watchers.clear();
3331
+ try {
3332
+ native.stopWatch(handleId);
3333
+ } catch {
3334
+ }
2396
3335
  }
2397
3336
  };
2398
3337
  }
3338
+ function watchWorkspace(rootDir, onEvent, options = {}) {
3339
+ const nativeWatcher = watchWorkspaceNative(rootDir, onEvent, options);
3340
+ if (!nativeWatcher) {
3341
+ throw new Error("FATAL: Native watcher is required but not available. Build the native module: npm run build:rust");
3342
+ }
3343
+ return nativeWatcher;
3344
+ }
2399
3345
 
2400
3346
  // packages/domain/engine/src/index.ts
2401
3347
  var DEFAULT_LARGE_FILE_THRESHOLD_BYTES = 10 * 1024 * 1024;
@@ -2418,8 +3364,8 @@ var configState = {
2418
3364
  var log6 = createLogger("engine");
2419
3365
  async function loadTailwindConfigFromPath(root, tailwindConfigPath) {
2420
3366
  if (!tailwindConfigPath) return void 0;
2421
- const configPath = path3.resolve(root, tailwindConfigPath);
2422
- if (!fs.existsSync(configPath)) {
3367
+ const configPath = path6__default.resolve(root, tailwindConfigPath);
3368
+ if (!fs4__default.existsSync(configPath)) {
2423
3369
  throw TwError.fromIo("CONFIG_NOT_FOUND", `tailwindConfigPath not found: ${configPath}`);
2424
3370
  }
2425
3371
  const imported = await import(pathToFileURL(configPath).href);
@@ -2482,11 +3428,11 @@ async function buildFromScan(scan, root, options, tailwindConfig) {
2482
3428
  };
2483
3429
  }
2484
3430
  function countWorkspacePackages(root) {
2485
- const packagesDir = path3.join(root, "packages");
2486
- if (!fs.existsSync(packagesDir)) return 0;
3431
+ const packagesDir = path6__default.join(root, "packages");
3432
+ if (!fs4__default.existsSync(packagesDir)) return 0;
2487
3433
  try {
2488
- return fs.readdirSync(packagesDir, { withFileTypes: true }).filter(
2489
- (entry) => entry.isDirectory() && fs.existsSync(path3.join(packagesDir, entry.name, "package.json"))
3434
+ return fs4__default.readdirSync(packagesDir, { withFileTypes: true }).filter(
3435
+ (entry) => entry.isDirectory() && fs4__default.existsSync(path6__default.join(packagesDir, entry.name, "package.json"))
2490
3436
  ).length;
2491
3437
  } catch {
2492
3438
  return 0;
@@ -2522,7 +3468,7 @@ function writeDashboardMetrics(root, mode, result, metrics) {
2522
3468
  async function createEngine(rawOptions = {}) {
2523
3469
  const options = parseEngineOptions(rawOptions);
2524
3470
  const root = options.root ?? process.cwd();
2525
- const resolvedRoot = path3.resolve(root);
3471
+ const resolvedRoot = path6__default.resolve(root);
2526
3472
  const plugins = rawOptions.plugins ?? [];
2527
3473
  const getTailwindConfig = async () => {
2528
3474
  if (configState.isLoaded()) return configState.getConfig();
@@ -2669,7 +3615,7 @@ async function createEngine(rawOptions = {}) {
2669
3615
  const shouldForceFullRescan = (event) => {
2670
3616
  if (event.type === "unlink") return false;
2671
3617
  try {
2672
- const stat = fs.statSync(event.filePath);
3618
+ const stat = fs4__default.statSync(event.filePath);
2673
3619
  if (stat.size > largeFileThreshold) {
2674
3620
  metrics.markSkippedLargeFile();
2675
3621
  return true;
@@ -2788,7 +3734,7 @@ async function createEngine(rawOptions = {}) {
2788
3734
 
2789
3735
  // packages/presentation/vite/src/schemas.ts
2790
3736
  init_src();
2791
- var formatIssuePath4 = (path11) => path11.length > 0 ? path11.map(
3737
+ var formatIssuePath4 = (path13) => path13.length > 0 ? path13.map(
2792
3738
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
2793
3739
  ).join(".") : "<root>";
2794
3740
  var formatIssues4 = (error) => error.issues.map((issue) => {
@@ -2834,14 +3780,14 @@ function warnDeprecated(options, key, message) {
2834
3780
  }
2835
3781
  }
2836
3782
  function isInsideDirectory(filePath, directory) {
2837
- const relative = path3.relative(directory, filePath);
2838
- return relative === "" || !relative.startsWith("..") && !path3.isAbsolute(relative);
3783
+ const relative = path6__default.relative(directory, filePath);
3784
+ return relative === "" || !relative.startsWith("..") && !path6__default.isAbsolute(relative);
2839
3785
  }
2840
3786
  function filterScanToDirs(scan, root, scanDirs) {
2841
- const resolvedDirs = scanDirs.map((dir) => path3.resolve(root, dir));
3787
+ const resolvedDirs = scanDirs.map((dir) => path6__default.resolve(root, dir));
2842
3788
  if (resolvedDirs.length === 0) return scan;
2843
3789
  const files = scan.files.filter((file) => {
2844
- const absoluteFile = path3.resolve(file.file);
3790
+ const absoluteFile = path6__default.resolve(file.file);
2845
3791
  return resolvedDirs.some((directory) => isInsideDirectory(absoluteFile, directory));
2846
3792
  });
2847
3793
  const uniqueClasses = Array.from(new Set(files.flatMap((file) => file.classes))).sort();
@@ -2852,9 +3798,9 @@ function filterScanToDirs(scan, root, scanDirs) {
2852
3798
  };
2853
3799
  }
2854
3800
  function writeJsonArtifact(root, relativePath, value) {
2855
- const outputPath = path3.resolve(root, relativePath);
2856
- fs.mkdirSync(path3.dirname(outputPath), { recursive: true });
2857
- fs.writeFileSync(outputPath, `${JSON.stringify(value, null, 2)}
3801
+ const outputPath = path6__default.resolve(root, relativePath);
3802
+ fs4__default.mkdirSync(path6__default.dirname(outputPath), { recursive: true });
3803
+ fs4__default.writeFileSync(outputPath, `${JSON.stringify(value, null, 2)}
2858
3804
  `);
2859
3805
  }
2860
3806
  function tailwindStyledPlugin(opts = {}) {