tailwind-styled-v4 5.0.9 → 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 (137) hide show
  1. package/CHANGELOG.md +15 -1
  2. package/dist/{analyzeWorkspace-DuJKh7Ty.d.mts → analyzeWorkspace-BS5O4rhC.d.mts} +47 -2
  3. package/dist/{analyzeWorkspace-Ct_NTAWt.d.ts → analyzeWorkspace-DDOQdzzI.d.ts} +47 -2
  4. package/dist/analyzer.d.mts +5 -3
  5. package/dist/analyzer.d.ts +5 -3
  6. package/dist/analyzer.js +563 -468
  7. package/dist/analyzer.js.map +1 -1
  8. package/dist/analyzer.mjs +562 -467
  9. package/dist/analyzer.mjs.map +1 -1
  10. package/dist/animate.d.mts +4 -7
  11. package/dist/animate.d.ts +4 -7
  12. package/dist/animate.js +171 -265
  13. package/dist/animate.js.map +1 -1
  14. package/dist/animate.mjs +165 -264
  15. package/dist/animate.mjs.map +1 -1
  16. package/dist/atomic.d.mts +22 -1
  17. package/dist/atomic.d.ts +22 -1
  18. package/dist/atomic.js +221 -165
  19. package/dist/atomic.js.map +1 -1
  20. package/dist/atomic.mjs +200 -165
  21. package/dist/atomic.mjs.map +1 -1
  22. package/dist/cli.d.mts +60 -1
  23. package/dist/cli.d.ts +60 -1
  24. package/dist/cli.js +1261 -1517
  25. package/dist/cli.js.map +1 -1
  26. package/dist/cli.mjs +1238 -1513
  27. package/dist/cli.mjs.map +1 -1
  28. package/dist/compiler.d.mts +38 -7
  29. package/dist/compiler.d.ts +38 -7
  30. package/dist/compiler.js +174 -197
  31. package/dist/compiler.js.map +1 -1
  32. package/dist/compiler.mjs +151 -194
  33. package/dist/compiler.mjs.map +1 -1
  34. package/dist/devtools.js +7 -31
  35. package/dist/devtools.js.map +1 -1
  36. package/dist/devtools.mjs +7 -31
  37. package/dist/devtools.mjs.map +1 -1
  38. package/dist/engine.d.mts +134 -63
  39. package/dist/engine.d.ts +134 -63
  40. package/dist/engine.js +2863 -2482
  41. package/dist/engine.js.map +1 -1
  42. package/dist/engine.mjs +2852 -2485
  43. package/dist/engine.mjs.map +1 -1
  44. package/dist/{index-eWAocnD2.d.mts → index-NDINUhLN.d.mts} +3 -1
  45. package/dist/{index-eWAocnD2.d.ts → index-NDINUhLN.d.ts} +3 -1
  46. package/dist/index.d.mts +45 -32
  47. package/dist/index.d.ts +45 -32
  48. package/dist/index.js +271 -158
  49. package/dist/index.js.map +1 -1
  50. package/dist/index.mjs +251 -158
  51. package/dist/index.mjs.map +1 -1
  52. package/dist/{liveTokenEngine-DSUk88P6.d.ts → liveTokenEngine-CN9ian1R.d.ts} +1 -1
  53. package/dist/{liveTokenEngine-CX5_0c4q.d.mts → liveTokenEngine-DKoWRtqH.d.mts} +1 -1
  54. package/dist/next.js +20 -39
  55. package/dist/next.js.map +1 -1
  56. package/dist/next.mjs +18 -37
  57. package/dist/next.mjs.map +1 -1
  58. package/dist/plugin-api.d.mts +8 -2
  59. package/dist/plugin-api.d.ts +8 -2
  60. package/dist/plugin-api.js +14 -2
  61. package/dist/plugin-api.js.map +1 -1
  62. package/dist/plugin-api.mjs +14 -3
  63. package/dist/plugin-api.mjs.map +1 -1
  64. package/dist/plugin-registry.js +51 -11
  65. package/dist/plugin-registry.js.map +1 -1
  66. package/dist/plugin-registry.mjs +51 -11
  67. package/dist/plugin-registry.mjs.map +1 -1
  68. package/dist/plugin.d.mts +5 -7
  69. package/dist/plugin.d.ts +5 -7
  70. package/dist/plugin.js +16 -15
  71. package/dist/plugin.js.map +1 -1
  72. package/dist/plugin.mjs +16 -16
  73. package/dist/plugin.mjs.map +1 -1
  74. package/dist/rspack.js +17 -38
  75. package/dist/rspack.js.map +1 -1
  76. package/dist/rspack.mjs +15 -36
  77. package/dist/rspack.mjs.map +1 -1
  78. package/dist/runtime.d.mts +2 -2
  79. package/dist/runtime.d.ts +2 -2
  80. package/dist/scanner.d.mts +10 -1
  81. package/dist/scanner.d.ts +10 -1
  82. package/dist/scanner.js +298 -124
  83. package/dist/scanner.js.map +1 -1
  84. package/dist/scanner.mjs +296 -124
  85. package/dist/scanner.mjs.map +1 -1
  86. package/dist/shared.d.mts +1 -1
  87. package/dist/shared.d.ts +1 -1
  88. package/dist/shared.js +104 -176
  89. package/dist/shared.js.map +1 -1
  90. package/dist/shared.mjs +85 -176
  91. package/dist/shared.mjs.map +1 -1
  92. package/dist/storybook-addon.d.mts +1 -1
  93. package/dist/storybook-addon.d.ts +1 -1
  94. package/dist/svelte.d.mts +1 -1
  95. package/dist/svelte.d.ts +1 -1
  96. package/dist/svelte.js +166 -3
  97. package/dist/svelte.js.map +1 -1
  98. package/dist/svelte.mjs +143 -1
  99. package/dist/svelte.mjs.map +1 -1
  100. package/dist/syntax.js +21 -21
  101. package/dist/syntax.js.map +1 -1
  102. package/dist/syntax.mjs +21 -21
  103. package/dist/syntax.mjs.map +1 -1
  104. package/dist/testing.js +9 -1
  105. package/dist/testing.js.map +1 -1
  106. package/dist/testing.mjs +9 -1
  107. package/dist/testing.mjs.map +1 -1
  108. package/dist/theme.d.mts +2 -2
  109. package/dist/theme.d.ts +2 -2
  110. package/dist/theme.js +40 -112
  111. package/dist/theme.js.map +1 -1
  112. package/dist/theme.mjs +37 -110
  113. package/dist/theme.mjs.map +1 -1
  114. package/dist/turbopackLoader.js +79 -124
  115. package/dist/turbopackLoader.js.map +1 -1
  116. package/dist/turbopackLoader.mjs +63 -122
  117. package/dist/turbopackLoader.mjs.map +1 -1
  118. package/dist/tw.js +1256 -1517
  119. package/dist/tw.js.map +1 -1
  120. package/dist/tw.mjs +1236 -1513
  121. package/dist/tw.mjs.map +1 -1
  122. package/dist/vite.js +1783 -823
  123. package/dist/vite.js.map +1 -1
  124. package/dist/vite.mjs +1767 -821
  125. package/dist/vite.mjs.map +1 -1
  126. package/dist/vue.d.mts +1 -1
  127. package/dist/vue.d.ts +1 -1
  128. package/dist/vue.js +165 -4
  129. package/dist/vue.js.map +1 -1
  130. package/dist/vue.mjs +141 -1
  131. package/dist/vue.mjs.map +1 -1
  132. package/dist/webpackLoader.js +65 -108
  133. package/dist/webpackLoader.js.map +1 -1
  134. package/dist/webpackLoader.mjs +45 -104
  135. package/dist/webpackLoader.mjs.map +1 -1
  136. package/native/tailwind-styled-native.node +0 -0
  137. package/package.json +22 -24
package/dist/tw.mjs CHANGED
@@ -1,11 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import path3, { join, extname } from 'path';
3
- import { pathToFileURL, fileURLToPath } from 'url';
4
- import { z } from 'zod';
5
- import fs8, { readFileSync, readdirSync } from 'fs';
6
2
  import { createRequire } from 'module';
7
- import { Worker } from 'worker_threads';
8
- import fs4 from 'fs/promises';
3
+ import * as fs11 from 'fs';
4
+ import fs11__default, { readFileSync, readdirSync } from 'fs';
5
+ import * as path6 from 'path';
6
+ import path6__default, { join, extname } from 'path';
7
+ import 'crypto';
8
+ import { fileURLToPath, pathToFileURL } from 'url';
9
+ import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';
10
+ import { availableParallelism } from 'os';
11
+ import { z } from 'zod';
12
+ import fs7 from 'fs/promises';
9
13
  import { isTTY, spinner, note, outro, intro, text, isCancel, select, confirm } from '@clack/prompts';
10
14
  import { parseArgs } from 'util';
11
15
  import { spawn } from 'child_process';
@@ -984,8 +988,8 @@ var require_command = __commonJS({
984
988
  "packages/infrastructure/cli/node_modules/commander/lib/command.js"(exports$1) {
985
989
  var EventEmitter = __require("events").EventEmitter;
986
990
  var childProcess = __require("child_process");
987
- var path26 = __require("path");
988
- var fs12 = __require("fs");
991
+ var path29 = __require("path");
992
+ var fs15 = __require("fs");
989
993
  var process2 = __require("process");
990
994
  var { Argument: Argument2, humanReadableArgName } = require_argument();
991
995
  var { CommanderError: CommanderError2 } = require_error();
@@ -1916,11 +1920,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1916
1920
  let launchWithNode = false;
1917
1921
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1918
1922
  function findFile(baseDir, baseName) {
1919
- const localBin = path26.resolve(baseDir, baseName);
1920
- if (fs12.existsSync(localBin)) return localBin;
1921
- if (sourceExt.includes(path26.extname(baseName))) return void 0;
1923
+ const localBin = path29.resolve(baseDir, baseName);
1924
+ if (fs15.existsSync(localBin)) return localBin;
1925
+ if (sourceExt.includes(path29.extname(baseName))) return void 0;
1922
1926
  const foundExt = sourceExt.find(
1923
- (ext) => fs12.existsSync(`${localBin}${ext}`)
1927
+ (ext) => fs15.existsSync(`${localBin}${ext}`)
1924
1928
  );
1925
1929
  if (foundExt) return `${localBin}${foundExt}`;
1926
1930
  return void 0;
@@ -1932,21 +1936,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
1932
1936
  if (this._scriptPath) {
1933
1937
  let resolvedScriptPath;
1934
1938
  try {
1935
- resolvedScriptPath = fs12.realpathSync(this._scriptPath);
1939
+ resolvedScriptPath = fs15.realpathSync(this._scriptPath);
1936
1940
  } catch (err) {
1937
1941
  resolvedScriptPath = this._scriptPath;
1938
1942
  }
1939
- executableDir = path26.resolve(
1940
- path26.dirname(resolvedScriptPath),
1943
+ executableDir = path29.resolve(
1944
+ path29.dirname(resolvedScriptPath),
1941
1945
  executableDir
1942
1946
  );
1943
1947
  }
1944
1948
  if (executableDir) {
1945
1949
  let localFile = findFile(executableDir, executableFile);
1946
1950
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1947
- const legacyName = path26.basename(
1951
+ const legacyName = path29.basename(
1948
1952
  this._scriptPath,
1949
- path26.extname(this._scriptPath)
1953
+ path29.extname(this._scriptPath)
1950
1954
  );
1951
1955
  if (legacyName !== this._name) {
1952
1956
  localFile = findFile(
@@ -1957,7 +1961,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1957
1961
  }
1958
1962
  executableFile = localFile || executableFile;
1959
1963
  }
1960
- launchWithNode = sourceExt.includes(path26.extname(executableFile));
1964
+ launchWithNode = sourceExt.includes(path29.extname(executableFile));
1961
1965
  let proc;
1962
1966
  if (process2.platform !== "win32") {
1963
1967
  if (launchWithNode) {
@@ -2797,7 +2801,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2797
2801
  * @return {Command}
2798
2802
  */
2799
2803
  nameFromFilename(filename) {
2800
- this._name = path26.basename(filename, path26.extname(filename));
2804
+ this._name = path29.basename(filename, path29.extname(filename));
2801
2805
  return this;
2802
2806
  }
2803
2807
  /**
@@ -2811,9 +2815,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2811
2815
  * @param {string} [path]
2812
2816
  * @return {(string|null|Command)}
2813
2817
  */
2814
- executableDir(path27) {
2815
- if (path27 === void 0) return this._executableDir;
2816
- this._executableDir = path27;
2818
+ executableDir(path30) {
2819
+ if (path30 === void 0) return this._executableDir;
2820
+ this._executableDir = path30;
2817
2821
  return this;
2818
2822
  }
2819
2823
  /**
@@ -3153,45 +3157,6 @@ var init_esmHelpers = __esm({
3153
3157
  _nodeUrl = null;
3154
3158
  }
3155
3159
  });
3156
-
3157
- // packages/domain/shared/src/native-resolution.ts
3158
- function getNodeModuleRef2() {
3159
- if (isBrowser2) return null;
3160
- if (nodeModuleRef2 !== null) return nodeModuleRef2;
3161
- try {
3162
- const test = typeof __require === "function" ? __require("module") : null;
3163
- nodeModuleRef2 = test;
3164
- return test;
3165
- } catch {
3166
- nodeModuleRef2 = null;
3167
- return null;
3168
- }
3169
- }
3170
- function getNodeFs() {
3171
- if (isBrowser2) return { existsSync: () => false };
3172
- const nodeRequire = getNodeModuleRef2();
3173
- if (!nodeRequire) return { existsSync: () => false };
3174
- if (!_nodeFs) _nodeFs = nodeRequire.createRequire(import.meta.url)("node:fs");
3175
- return _nodeFs;
3176
- }
3177
- function getNodePath2() {
3178
- if (isBrowser2) return { resolve: () => "", dirname: "" };
3179
- const nodeRequire = getNodeModuleRef2();
3180
- if (!nodeRequire) return { resolve: () => "", dirname: "" };
3181
- if (!_nodePath2) _nodePath2 = nodeRequire.createRequire(import.meta.url)("node:path");
3182
- return _nodePath2;
3183
- }
3184
- function getRequire(_importMetaUrl) {
3185
- if (isBrowser2) return () => {
3186
- throw new Error("node:module not available");
3187
- };
3188
- const nodeRequire = getNodeModuleRef2();
3189
- if (!nodeRequire) return () => {
3190
- throw new Error("require not available");
3191
- };
3192
- if (!_require) _require = nodeRequire.createRequire(_importMetaUrl);
3193
- return _require;
3194
- }
3195
3160
  function platformKey() {
3196
3161
  if (isBrowser2) return "browser";
3197
3162
  return `${process.platform}-${process.arch}`;
@@ -3202,24 +3167,21 @@ function resolveNativeBinary(runtimeDir) {
3202
3167
  if (isBrowser2) {
3203
3168
  return { path: null, source: "not-found", platform, tried: ["not available in browser"] };
3204
3169
  }
3205
- const fs12 = getNodeFs();
3206
- const path26 = getNodePath2();
3207
- const _req = getRequire(import.meta.url);
3170
+ if (process.env.TWS_DISABLE_NATIVE === "1") {
3171
+ return { path: null, source: "not-found", platform, tried: [] };
3172
+ }
3208
3173
  const envPath = process.env.TW_NATIVE_PATH?.trim();
3209
3174
  if (envPath) {
3210
- if (fs12.existsSync(envPath)) {
3175
+ if (fs11.existsSync(envPath)) {
3211
3176
  return { path: envPath, source: "env", platform, tried };
3212
3177
  }
3213
3178
  tried.push(`env:${envPath} (not found)`);
3214
3179
  }
3215
- if (process.env.TWS_NO_NATIVE === "1" || process.env.TWS_NO_RUST === "1" || process.env.TWS_DISABLE_NATIVE === "1") {
3216
- return { path: null, source: "not-found", platform, tried: ["disabled by env"] };
3217
- }
3218
3180
  const prebuiltPkgs = PLATFORM_MAP[platform] ?? [];
3219
3181
  for (const pkg of prebuiltPkgs) {
3220
3182
  try {
3221
- const candidate = _req.resolve(`${pkg}/tailwind_styled_parser.node`);
3222
- if (fs12.existsSync(candidate)) {
3183
+ const candidate = _require.resolve(`${pkg}/tailwind_styled_parser.node`);
3184
+ if (fs11.existsSync(candidate)) {
3223
3185
  return { path: candidate, source: "prebuilt", platform, tried };
3224
3186
  }
3225
3187
  tried.push(`prebuilt:${pkg} (resolved but missing)`);
@@ -3229,30 +3191,43 @@ function resolveNativeBinary(runtimeDir) {
3229
3191
  }
3230
3192
  const cwd2 = process.cwd();
3231
3193
  const base = runtimeDir ?? cwd2;
3232
- const localCandidates = [
3233
- path26.resolve(base, "tailwind_styled_parser.node"),
3234
- path26.resolve(base, "..", "tailwind_styled_parser.node"),
3235
- path26.resolve(cwd2, "native", "tailwind_styled_parser.node"),
3236
- path26.resolve(cwd2, "native", "target", "release", "tailwind_styled_parser.node"),
3237
- // napi-rs conventional output
3238
- path26.resolve(base, `tailwind_styled_parser.${platform}.node`)
3239
- ];
3194
+ const napiPlatform = platform === "linux-x64" ? "linux-x64-gnu" : platform === "linux-arm64" ? "linux-arm64-gnu" : platform;
3195
+ const BINARY_NAMES = ["tailwind-styled-native", "tailwind_styled_parser"];
3196
+ const localCandidates = [];
3197
+ for (const bin of BINARY_NAMES) {
3198
+ localCandidates.push(path6.resolve(base, `${bin}.node`));
3199
+ localCandidates.push(path6.resolve(base, "..", `${bin}.node`));
3200
+ localCandidates.push(path6.resolve(base, `${bin}.${platform}.node`));
3201
+ localCandidates.push(path6.resolve(base, `${bin}.${napiPlatform}.node`));
3202
+ }
3203
+ for (const startDir of [cwd2, base]) {
3204
+ let dir = startDir;
3205
+ for (let i = 0; i < 6; i++) {
3206
+ const nativeDir = path6.resolve(dir, "native");
3207
+ for (const bin of BINARY_NAMES) {
3208
+ localCandidates.push(path6.resolve(nativeDir, `${bin}.node`));
3209
+ localCandidates.push(path6.resolve(nativeDir, `${bin}.${platform}.node`));
3210
+ localCandidates.push(path6.resolve(nativeDir, `${bin}.${napiPlatform}.node`));
3211
+ localCandidates.push(path6.resolve(nativeDir, "target", "release", `${bin}.node`));
3212
+ }
3213
+ const parent = path6.resolve(dir, "..");
3214
+ if (parent === dir) break;
3215
+ dir = parent;
3216
+ }
3217
+ }
3240
3218
  for (const candidate of localCandidates) {
3241
3219
  tried.push(`local:${candidate}`);
3242
- if (fs12.existsSync(candidate)) {
3220
+ if (fs11.existsSync(candidate)) {
3243
3221
  return { path: candidate, source: "local", platform, tried };
3244
3222
  }
3245
3223
  }
3246
3224
  return { path: null, source: "not-found", platform, tried };
3247
3225
  }
3248
- var isBrowser2, nodeModuleRef2, _nodeFs, _nodePath2, _require, PLATFORM_MAP;
3226
+ var isBrowser2, _require, PLATFORM_MAP;
3249
3227
  var init_native_resolution = __esm({
3250
3228
  "packages/domain/shared/src/native-resolution.ts"() {
3251
3229
  isBrowser2 = typeof window !== "undefined" || typeof document !== "undefined";
3252
- nodeModuleRef2 = null;
3253
- _nodeFs = null;
3254
- _nodePath2 = null;
3255
- _require = null;
3230
+ _require = typeof __require !== "undefined" ? __require : createRequire(import.meta.url);
3256
3231
  PLATFORM_MAP = {
3257
3232
  "linux-x64": ["@tailwind-styled/native-linux-x64"],
3258
3233
  "linux-arm64": ["@tailwind-styled/native-linux-arm64"],
@@ -3263,41 +3238,6 @@ var init_native_resolution = __esm({
3263
3238
  };
3264
3239
  }
3265
3240
  });
3266
-
3267
- // packages/domain/shared/src/index.ts
3268
- function getNodeModuleRef3() {
3269
- if (isBrowser3) return null;
3270
- if (nodeModuleRef3 !== null) return nodeModuleRef3;
3271
- try {
3272
- const test = typeof __require === "function" ? __require("module") : null;
3273
- nodeModuleRef3 = test;
3274
- return test;
3275
- } catch {
3276
- nodeModuleRef3 = null;
3277
- return null;
3278
- }
3279
- }
3280
- function getNodeFs2() {
3281
- if (isBrowser3) throw new Error("node:fs not available in browser");
3282
- const nodeRequire = getNodeModuleRef3();
3283
- if (!nodeRequire) throw new Error("require not available");
3284
- if (!_nodeFs2) _nodeFs2 = nodeRequire.createRequire(import.meta.url)("node:fs");
3285
- return _nodeFs2;
3286
- }
3287
- function getNodePath3() {
3288
- if (isBrowser3) throw new Error("node:path not available in browser");
3289
- const nodeRequire = getNodeModuleRef3();
3290
- if (!nodeRequire) throw new Error("require not available");
3291
- if (!_nodePath3) _nodePath3 = nodeRequire.createRequire(import.meta.url)("node:path");
3292
- return _nodePath3;
3293
- }
3294
- function getNodeUrl2() {
3295
- if (isBrowser3) throw new Error("node:url not available in browser");
3296
- const nodeRequire = getNodeModuleRef3();
3297
- if (!nodeRequire) throw new Error("require not available");
3298
- if (!_nodeUrl2) _nodeUrl2 = nodeRequire.createRequire(import.meta.url)("node:url");
3299
- return _nodeUrl2;
3300
- }
3301
3241
  function createLogger(namespace) {
3302
3242
  const prefix = `[${namespace}]`;
3303
3243
  return {
@@ -3327,9 +3267,9 @@ function createDebugLogger(namespace, label) {
3327
3267
  }
3328
3268
  };
3329
3269
  }
3330
- function formatIssuePath(path26) {
3331
- if (!path26 || path26.length === 0) return "(root)";
3332
- return path26.map(
3270
+ function formatIssuePath(path29) {
3271
+ if (!path29 || path29.length === 0) return "(root)";
3272
+ return path29.map(
3333
3273
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
3334
3274
  ).join(".");
3335
3275
  }
@@ -3337,17 +3277,12 @@ function wrapUnknownError(domain, code, error) {
3337
3277
  return TwError.wrap(domain, code, error);
3338
3278
  }
3339
3279
  function loadNativeBinding(options) {
3340
- if (isBrowser3) {
3341
- return { binding: null, loadErrors: [{ path: "", message: "Native bindings not available in browser" }] };
3342
- }
3343
3280
  const { runtimeDir, candidates, isValid } = options;
3344
3281
  const loadErrors = [];
3345
- const path26 = getNodePath3();
3346
- const fs12 = getNodeFs2();
3347
3282
  for (const candidate of candidates) {
3348
- const candidatePath = path26.resolve(runtimeDir, candidate);
3283
+ const candidatePath = path6__default.resolve(runtimeDir, candidate);
3349
3284
  try {
3350
- if (!fs12.existsSync(candidatePath) && !fs12.existsSync(candidatePath + ".node")) {
3285
+ if (!fs11__default.existsSync(candidatePath) && !fs11__default.existsSync(candidatePath + ".node")) {
3351
3286
  continue;
3352
3287
  }
3353
3288
  const mod = requireNativeModule(candidatePath);
@@ -3361,74 +3296,58 @@ function loadNativeBinding(options) {
3361
3296
  }
3362
3297
  return { binding: null, loadErrors };
3363
3298
  }
3364
- function getRequire2() {
3365
- if (isBrowser3) return (() => {
3366
- throw new Error("require not available in browser");
3367
- });
3368
- const nodeRequire = getNodeModuleRef3();
3369
- if (!nodeRequire) return (() => {
3370
- throw new Error("require not available");
3371
- });
3372
- return nodeRequire.createRequire(import.meta.url);
3373
- }
3374
- function requireNativeModule(path26) {
3375
- return _require2(path26);
3299
+ function requireNativeModule(p) {
3300
+ return _require2(p);
3376
3301
  }
3377
3302
  function resolveNativeBindingCandidates(options) {
3378
- if (isBrowser3) return [];
3379
- const { runtimeDir, envVarNames = [], includeDefaultCandidates = true, enforceNodeExtensionForEnvPath = false } = options;
3303
+ const {
3304
+ envVarNames = ["TW_NATIVE_PATH", "TWS_NATIVE_PATH"],
3305
+ includeDefaultCandidates = true,
3306
+ enforceNodeExtensionForEnvPath = false
3307
+ } = options;
3308
+ const runtimeDir = options.runtimeDir || process.cwd();
3380
3309
  const candidates = [];
3381
- const path26 = getNodePath3();
3382
- const fs12 = getNodeFs2();
3383
3310
  for (const envVar of envVarNames) {
3384
3311
  const envPath = process.env[envVar];
3385
3312
  if (envPath) {
3386
- if (enforceNodeExtensionForEnvPath && !envPath.endsWith(".node")) {
3387
- candidates.push(envPath + ".node");
3388
- } else {
3389
- candidates.push(envPath);
3390
- }
3313
+ candidates.push(enforceNodeExtensionForEnvPath && !envPath.endsWith(".node") ? envPath + ".node" : envPath);
3391
3314
  }
3392
3315
  }
3393
3316
  if (!includeDefaultCandidates) return candidates;
3394
- if (fs12.existsSync(runtimeDir)) {
3317
+ if (fs11__default.existsSync(runtimeDir)) {
3395
3318
  try {
3396
- const entries = fs12.readdirSync(runtimeDir);
3397
- for (const entry of entries) {
3398
- if (entry.endsWith(".node")) {
3399
- candidates.push(entry);
3400
- }
3319
+ for (const entry of fs11__default.readdirSync(runtimeDir)) {
3320
+ if (entry.endsWith(".node")) candidates.push(entry);
3401
3321
  }
3402
3322
  } catch {
3403
3323
  }
3404
3324
  }
3405
- const platform = typeof process !== "undefined" ? process.platform : "";
3406
- const ext = platform === "win32" ? ".dll" : platform === "darwin" ? ".dylib" : ".so";
3407
- const defaultBindingName = `tailwind_styled_parser${ext}`;
3408
- candidates.push(path26.resolve(runtimeDir, "..", "..", "..", "native", defaultBindingName));
3409
- candidates.push(path26.resolve(runtimeDir, "..", "..", "..", "..", "native", defaultBindingName));
3410
- candidates.push(path26.resolve(process.cwd(), "native", defaultBindingName));
3325
+ const BINARY_NAMES = ["tailwind-styled-native", "tailwind_styled_parser"];
3326
+ const napiPlatform = process.platform === "linux" && process.arch === "x64" ? "linux-x64-gnu" : process.platform === "linux" && process.arch === "arm64" ? "linux-arm64-gnu" : `${process.platform}-${process.arch}`;
3327
+ for (const bin of BINARY_NAMES) {
3328
+ candidates.push(path6__default.resolve(runtimeDir, `${bin}.node`));
3329
+ candidates.push(path6__default.resolve(runtimeDir, `${bin}.${napiPlatform}.node`));
3330
+ candidates.push(path6__default.resolve(runtimeDir, "..", "..", "..", "..", "native", `${bin}.node`));
3331
+ candidates.push(path6__default.resolve(runtimeDir, "..", "..", "..", "..", "native", `${bin}.${napiPlatform}.node`));
3332
+ candidates.push(path6__default.resolve(runtimeDir, "..", "..", "..", "native", `${bin}.node`));
3333
+ candidates.push(path6__default.resolve(process.cwd(), "native", `${bin}.node`));
3334
+ candidates.push(path6__default.resolve(process.cwd(), "native", `${bin}.${napiPlatform}.node`));
3335
+ }
3411
3336
  return Array.from(new Set(candidates));
3412
3337
  }
3413
3338
  function resolveRuntimeDir(dir, importMetaUrl) {
3414
- if (isBrowser3) return "";
3415
- if (dir) return getNodePath3().resolve(dir);
3339
+ if (dir) return path6__default.resolve(dir);
3416
3340
  try {
3417
- return getNodeUrl2().fileURLToPath(importMetaUrl);
3341
+ return path6__default.dirname(fileURLToPath(importMetaUrl));
3418
3342
  } catch {
3419
3343
  return process.cwd();
3420
3344
  }
3421
3345
  }
3422
- var isBrowser3, nodeModuleRef3, _nodeFs2, _nodePath3, _nodeUrl2, TwError, _require2;
3346
+ var TwError, _require2;
3423
3347
  var init_src = __esm({
3424
3348
  "packages/domain/shared/src/index.ts"() {
3425
3349
  init_esmHelpers();
3426
3350
  init_native_resolution();
3427
- isBrowser3 = typeof window !== "undefined" || typeof document !== "undefined";
3428
- nodeModuleRef3 = null;
3429
- _nodeFs2 = null;
3430
- _nodePath3 = null;
3431
- _nodeUrl2 = null;
3432
3351
  TwError = class _TwError extends Error {
3433
3352
  /** @deprecated Gunakan source */
3434
3353
  domain;
@@ -3462,8 +3381,8 @@ var init_src = __esm({
3462
3381
  /** Buat TwError dari ZodError — dukung shape Zod v3 (`errors`) dan v4 (`issues`). */
3463
3382
  static fromZod(err) {
3464
3383
  const first = err.issues?.[0] ?? err.errors?.[0];
3465
- const path26 = formatIssuePath(first?.path);
3466
- const message = first ? `${path26}: ${first.message}` : "Schema validation failed";
3384
+ const path29 = formatIssuePath(first?.path);
3385
+ const message = first ? `${path29}: ${first.message}` : "Schema validation failed";
3467
3386
  return new _TwError("validation", "SCHEMA_VALIDATION_FAILED", message, err);
3468
3387
  }
3469
3388
  static wrap(source, code, err) {
@@ -3481,21 +3400,33 @@ var init_src = __esm({
3481
3400
  return `[${this.source.toUpperCase()}:${this.code}] ${this.message}`;
3482
3401
  }
3483
3402
  };
3484
- _require2 = getRequire2();
3403
+ _require2 = createRequire(import.meta.url);
3485
3404
  }
3486
3405
  });
3487
3406
 
3488
3407
  // packages/domain/scanner/src/native-bridge.ts
3489
3408
  var native_bridge_exports = {};
3490
3409
  __export(native_bridge_exports, {
3410
+ batchExtractClassesNative: () => batchExtractClassesNative,
3491
3411
  cachePriorityNative: () => cachePriorityNative,
3492
3412
  cacheReadNative: () => cacheReadNative,
3493
3413
  cacheWriteNative: () => cacheWriteNative,
3414
+ collectFilesNative: () => collectFilesNative,
3415
+ computeCacheStatsNative: () => computeCacheStatsNative,
3494
3416
  extractClassesNative: () => extractClassesNative,
3417
+ generateSubComponentTypesNative: () => generateSubComponentTypesNative,
3495
3418
  hasNativeScannerBinding: () => hasNativeScannerBinding,
3496
3419
  hashContentNative: () => hashContentNative,
3497
3420
  isRustCacheAvailable: () => isRustCacheAvailable,
3421
+ pruneStaleEntriesNative: () => pruneStaleEntriesNative,
3422
+ rebuildWorkspaceResultNative: () => rebuildWorkspaceResultNative,
3498
3423
  resetScannerBridgeCache: () => resetScannerBridgeCache,
3424
+ scanCacheGet: () => scanCacheGet,
3425
+ scanCacheInvalidate: () => scanCacheInvalidate,
3426
+ scanCachePut: () => scanCachePut,
3427
+ scanCacheStats: () => scanCacheStats,
3428
+ scanFileNative: () => scanFileNative,
3429
+ scanFilesBatchNative: () => scanFilesBatchNative,
3499
3430
  scanWorkspaceNative: () => scanWorkspaceNative
3500
3431
  });
3501
3432
  function getDirname2() {
@@ -3503,7 +3434,7 @@ function getDirname2() {
3503
3434
  return __dirname;
3504
3435
  }
3505
3436
  if (typeof import.meta !== "undefined" && import.meta.url) {
3506
- return path3.dirname(fileURLToPath(import.meta.url));
3437
+ return path6__default.dirname(fileURLToPath(import.meta.url));
3507
3438
  }
3508
3439
  return process.cwd();
3509
3440
  }
@@ -3584,6 +3515,95 @@ function cachePriorityNative(mtimeMs, size, cachedMtimeMs, cachedSize, cachedHit
3584
3515
  }
3585
3516
  return result;
3586
3517
  }
3518
+ function batchExtractClassesNative(filePaths) {
3519
+ const binding = scannerGetBinding();
3520
+ if (!binding.batchExtractClasses) {
3521
+ throw new Error("FATAL: Native binding 'batchExtractClasses' is required but not available.");
3522
+ }
3523
+ return binding.batchExtractClasses(filePaths) ?? [];
3524
+ }
3525
+ function scanCacheGet(filePath, contentHash) {
3526
+ const binding = scannerGetBinding();
3527
+ if (!binding.scanCacheGet) {
3528
+ throw new Error("FATAL: Native binding 'scanCacheGet' is required but not available.");
3529
+ }
3530
+ return binding.scanCacheGet(filePath, contentHash) ?? null;
3531
+ }
3532
+ function scanCachePut(filePath, contentHash, classes, mtimeMs, size) {
3533
+ const binding = scannerGetBinding();
3534
+ if (!binding.scanCachePut) {
3535
+ throw new Error("FATAL: Native binding 'scanCachePut' is required but not available.");
3536
+ }
3537
+ binding.scanCachePut(filePath, contentHash, classes, mtimeMs, size);
3538
+ }
3539
+ function scanCacheInvalidate(filePath) {
3540
+ const binding = scannerGetBinding();
3541
+ if (!binding.scanCacheInvalidate) {
3542
+ throw new Error("FATAL: Native binding 'scanCacheInvalidate' is required but not available.");
3543
+ }
3544
+ binding.scanCacheInvalidate(filePath);
3545
+ }
3546
+ function scanCacheStats() {
3547
+ const binding = scannerGetBinding();
3548
+ if (!binding.scanCacheStats) {
3549
+ throw new Error("FATAL: Native binding 'scanCacheStats' is required but not available.");
3550
+ }
3551
+ return binding.scanCacheStats();
3552
+ }
3553
+ function scanFileNative(filePath) {
3554
+ const binding = scannerGetBinding();
3555
+ if (!binding.scanFile) {
3556
+ throw new Error("FATAL: Native binding 'scanFile' is required but not available.");
3557
+ }
3558
+ return binding.scanFile(filePath);
3559
+ }
3560
+ function collectFilesNative(root, extensions, ignoreDirs) {
3561
+ const binding = scannerGetBinding();
3562
+ if (!binding.collectFiles) return null;
3563
+ return binding.collectFiles(root, extensions, ignoreDirs);
3564
+ }
3565
+ function scanFilesBatchNative(filePaths) {
3566
+ const binding = scannerGetBinding();
3567
+ if (!binding.scanFilesBatch) {
3568
+ return filePaths.map((fp) => {
3569
+ try {
3570
+ const r = binding.scanFile?.(fp);
3571
+ return r ? { file: r.file, classes: r.classes, hash: r.hash ?? "" } : { file: fp, classes: [], hash: "" };
3572
+ } catch {
3573
+ return { file: fp, classes: [], hash: "" };
3574
+ }
3575
+ });
3576
+ }
3577
+ return binding.scanFilesBatch(filePaths);
3578
+ }
3579
+ function generateSubComponentTypesNative(root, outputPath) {
3580
+ const binding = scannerGetBinding();
3581
+ if (!binding.generateSubComponentTypes) return null;
3582
+ return binding.generateSubComponentTypes(root, outputPath ?? null);
3583
+ }
3584
+ function pruneStaleEntriesNative(entries, maxAgeMs, checkExists) {
3585
+ const binding = scannerGetBinding();
3586
+ if (!binding.pruneStaleEntries) return null;
3587
+ return binding.pruneStaleEntries(
3588
+ entries.map((e) => ({ file: e.file, lastSeenMs: e.lastSeenMs ?? 0 })),
3589
+ maxAgeMs ?? null,
3590
+ checkExists ?? null
3591
+ );
3592
+ }
3593
+ function rebuildWorkspaceResultNative(files) {
3594
+ const binding = scannerBridgeLoader.get();
3595
+ if (!binding?.rebuildWorkspaceResult) return null;
3596
+ try {
3597
+ return binding.rebuildWorkspaceResult(files);
3598
+ } catch {
3599
+ return null;
3600
+ }
3601
+ }
3602
+ function computeCacheStatsNative(filesClasses, sizes, top) {
3603
+ const binding = scannerGetBinding();
3604
+ if (!binding.computeCacheStats) return null;
3605
+ return binding.computeCacheStats(filesClasses, sizes, top ?? null);
3606
+ }
3587
3607
  var log, isValidScannerBinding, createScannerBridgeLoader, scannerBridgeLoader, scannerGetBinding, resetScannerBridgeCache;
3588
3608
  var init_native_bridge = __esm({
3589
3609
  "packages/domain/scanner/src/native-bridge.ts"() {
@@ -3668,8 +3688,8 @@ var init_native_bridge = __esm({
3668
3688
  }
3669
3689
  });
3670
3690
  function defaultCachePath(rootDir, cacheDir) {
3671
- const dir = cacheDir ? path3.resolve(rootDir, cacheDir) : path3.join(process.cwd(), ".cache", "tailwind-styled");
3672
- return path3.join(dir, "scanner-cache.json");
3691
+ const dir = cacheDir ? path6__default.resolve(rootDir, cacheDir) : path6__default.join(process.cwd(), ".cache", "tailwind-styled");
3692
+ return path6__default.join(dir, "scanner-cache.json");
3673
3693
  }
3674
3694
  function readCache(rootDir, cacheDir) {
3675
3695
  const cachePath = defaultCachePath(rootDir, cacheDir);
@@ -3710,16 +3730,117 @@ var init_cache_native = __esm({
3710
3730
  init_native_bridge();
3711
3731
  }
3712
3732
  });
3733
+ function collectFiles(rootDir, extensions, ignoreDirs) {
3734
+ const native = collectFilesNative(rootDir, extensions, ignoreDirs);
3735
+ if (native !== null) return native;
3736
+ const files = [];
3737
+ function walk(dir) {
3738
+ let entries;
3739
+ try {
3740
+ entries = fs11__default.readdirSync(dir, { withFileTypes: true });
3741
+ } catch {
3742
+ return;
3743
+ }
3744
+ for (const entry of entries) {
3745
+ const fullPath = path6__default.join(dir, entry.name);
3746
+ const rel = path6__default.relative(rootDir, fullPath);
3747
+ if (entry.isDirectory()) {
3748
+ const ignored = ignoreDirs.some((d) => entry.name === d || rel.startsWith(d + path6__default.sep));
3749
+ if (!ignored) walk(fullPath);
3750
+ } else if (isScannableFile(entry.name, extensions)) {
3751
+ files.push(fullPath);
3752
+ }
3753
+ }
3754
+ }
3755
+ walk(rootDir);
3756
+ return files;
3757
+ }
3758
+ function mergeResults(batchResults) {
3759
+ const files = batchResults.map((r) => ({
3760
+ file: r.file,
3761
+ classes: r.classes,
3762
+ hash: r.content_hash
3763
+ }));
3764
+ const native = rebuildWorkspaceResultNative(files);
3765
+ if (native) return native;
3766
+ const unique = new Set(files.flatMap((f) => f.classes));
3767
+ return { files, totalFiles: files.length, uniqueClasses: Array.from(unique).sort() };
3768
+ }
3769
+ function runChunkInWorker(filePaths) {
3770
+ return new Promise((resolve2, reject) => {
3771
+ const worker = new Worker(_workerFilename, {
3772
+ workerData: { filePaths }
3773
+ });
3774
+ worker.once("message", (payload) => {
3775
+ if (payload.ok) {
3776
+ resolve2(payload.results);
3777
+ } else {
3778
+ reject(new Error(payload.error ?? "parallel-scanner worker failed"));
3779
+ }
3780
+ });
3781
+ worker.once("error", reject);
3782
+ worker.once("exit", (code) => {
3783
+ if (code !== 0) reject(new Error(`parallel-scanner worker exited with code ${code}`));
3784
+ });
3785
+ });
3786
+ }
3787
+ async function scanWorkspaceParallel(rootDir, options = {}) {
3788
+ const {
3789
+ extensions = DEFAULT_EXTENSIONS,
3790
+ ignoreDirs = DEFAULT_IGNORES,
3791
+ maxWorkers = Math.max(1, availableParallelism() - 1),
3792
+ chunkSize = DEFAULT_CHUNK_SIZE
3793
+ } = options;
3794
+ const files = collectFiles(path6__default.resolve(rootDir), extensions, ignoreDirs);
3795
+ if (files.length < PARALLEL_THRESHOLD) {
3796
+ return mergeResults(batchExtractClassesNative(files));
3797
+ }
3798
+ const chunks = [];
3799
+ for (let i = 0; i < files.length; i += chunkSize) {
3800
+ chunks.push(files.slice(i, i + chunkSize));
3801
+ }
3802
+ const allResults = [];
3803
+ for (let i = 0; i < chunks.length; i += maxWorkers) {
3804
+ const batch = chunks.slice(i, i + maxWorkers);
3805
+ const batchResults = await Promise.all(batch.map(runChunkInWorker));
3806
+ allResults.push(...batchResults.flat());
3807
+ }
3808
+ return mergeResults(allResults);
3809
+ }
3810
+ var PARALLEL_THRESHOLD, DEFAULT_CHUNK_SIZE, _workerFilename;
3811
+ var init_parallel_scanner = __esm({
3812
+ "packages/domain/scanner/src/parallel-scanner.ts"() {
3813
+ init_src2();
3814
+ init_native_bridge();
3815
+ PARALLEL_THRESHOLD = 50;
3816
+ DEFAULT_CHUNK_SIZE = 150;
3817
+ if (!isMainThread && parentPort) {
3818
+ const { filePaths } = workerData;
3819
+ try {
3820
+ const results = batchExtractClassesNative(filePaths);
3821
+ const msg = { ok: true, results };
3822
+ parentPort.postMessage(msg);
3823
+ } catch (error) {
3824
+ const msg = {
3825
+ ok: false,
3826
+ error: error instanceof Error ? error.message : String(error)
3827
+ };
3828
+ parentPort.postMessage(msg);
3829
+ }
3830
+ }
3831
+ _workerFilename = typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url);
3832
+ }
3833
+ });
3713
3834
  var formatIssuePath2, formatIssues, parseWithSchema, NonNegativeIntegerSchema, ScanWorkspaceOptionsSchema, ScanFileResultSchema, ScanWorkspaceResultSchema, ScannerWorkerSuccessMessageSchema, ScannerWorkerErrorMessageSchema, ScannerWorkerMessageSchema, parseScanWorkspaceOptions, parseScanWorkspaceResult, parseScannerWorkerMessage;
3714
3835
  var init_schemas = __esm({
3715
3836
  "packages/domain/scanner/src/schemas.ts"() {
3716
3837
  init_src();
3717
- formatIssuePath2 = (path26) => path26.length > 0 ? path26.map(
3838
+ formatIssuePath2 = (path29) => path29.length > 0 ? path29.map(
3718
3839
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
3719
3840
  ).join(".") : "<root>";
3720
3841
  formatIssues = (error) => error.issues.map((issue) => {
3721
- const path26 = formatIssuePath2(issue.path);
3722
- return `${path26}: ${issue.message}`;
3842
+ const path29 = formatIssuePath2(issue.path);
3843
+ return `${path29}: ${issue.message}`;
3723
3844
  }).join("; ");
3724
3845
  parseWithSchema = (schema, data, label) => {
3725
3846
  const parsed = schema.safeParse(data);
@@ -3774,12 +3895,29 @@ var init_schemas = __esm({
3774
3895
  parseScannerWorkerMessage = (message) => parseWithSchema(ScannerWorkerMessageSchema, message, "scanner worker message is invalid");
3775
3896
  }
3776
3897
  });
3898
+
3899
+ // packages/domain/scanner/src/index.ts
3900
+ var src_exports = {};
3901
+ __export(src_exports, {
3902
+ DEFAULT_EXTENSIONS: () => DEFAULT_EXTENSIONS,
3903
+ DEFAULT_IGNORES: () => DEFAULT_IGNORES,
3904
+ batchExtractClassesNative: () => batchExtractClassesNative,
3905
+ extractClassesNative: () => extractClassesNative,
3906
+ isScannableFile: () => isScannableFile,
3907
+ parseScanWorkspaceOptions: () => parseScanWorkspaceOptions,
3908
+ parseScanWorkspaceResult: () => parseScanWorkspaceResult,
3909
+ parseScannerWorkerMessage: () => parseScannerWorkerMessage,
3910
+ scanFile: () => scanFile,
3911
+ scanSource: () => scanSource,
3912
+ scanWorkspace: () => scanWorkspace,
3913
+ scanWorkspaceAsync: () => scanWorkspaceAsync
3914
+ });
3777
3915
  function getRuntimeDir() {
3778
3916
  if (typeof __dirname !== "undefined" && __dirname.length > 0) {
3779
3917
  return __dirname;
3780
3918
  }
3781
3919
  if (typeof import.meta !== "undefined" && import.meta.url) {
3782
- return path3.dirname(fileURLToPath(import.meta.url));
3920
+ return path6__default.dirname(fileURLToPath(import.meta.url));
3783
3921
  }
3784
3922
  return process.cwd();
3785
3923
  }
@@ -3789,17 +3927,17 @@ function resolveScannerWorkerModulePath() {
3789
3927
  return __dirname;
3790
3928
  }
3791
3929
  if (typeof import.meta !== "undefined" && import.meta.url) {
3792
- return path3.dirname(fileURLToPath(import.meta.url));
3930
+ return path6__default.dirname(fileURLToPath(import.meta.url));
3793
3931
  }
3794
3932
  return process.cwd();
3795
3933
  })();
3796
3934
  const candidates = [
3797
- path3.resolve(runtimeDir, "worker.cjs"),
3798
- path3.resolve(runtimeDir, "worker.js"),
3799
- path3.resolve(runtimeDir, "worker.ts")
3935
+ path6__default.resolve(runtimeDir, "worker.cjs"),
3936
+ path6__default.resolve(runtimeDir, "worker.js"),
3937
+ path6__default.resolve(runtimeDir, "worker.ts")
3800
3938
  ];
3801
3939
  for (const candidate of candidates) {
3802
- if (fs8.existsSync(candidate)) return candidate;
3940
+ if (fs11__default.existsSync(candidate)) return candidate;
3803
3941
  }
3804
3942
  return null;
3805
3943
  }
@@ -3809,7 +3947,7 @@ function scanWorkspaceInWorker(rootDir, options) {
3809
3947
  if (!modulePath) {
3810
3948
  return Promise.reject(new Error("scanner worker module path could not be resolved"));
3811
3949
  }
3812
- return new Promise((resolve, reject) => {
3950
+ return new Promise((resolve2, reject) => {
3813
3951
  const settleState = { settled: false };
3814
3952
  const worker = new Worker(modulePath, { workerData: { rootDir, options: normalizedOptions } });
3815
3953
  const timeout = setTimeout(() => {
@@ -3829,7 +3967,7 @@ function scanWorkspaceInWorker(rootDir, options) {
3829
3967
  const message = parseScannerWorkerMessage(payload);
3830
3968
  finish(() => {
3831
3969
  if (message?.ok) {
3832
- resolve(parseScanWorkspaceResult(message.result));
3970
+ resolve2(parseScanWorkspaceResult(message.result));
3833
3971
  return;
3834
3972
  }
3835
3973
  reject(new Error(message?.error ?? "scanner worker failed without an error message"));
@@ -3856,19 +3994,19 @@ function collectCandidates(rootDir, ignoreDirectories, extensionSet) {
3856
3994
  if (!currentDir) continue;
3857
3995
  const entries = (() => {
3858
3996
  try {
3859
- return fs8.readdirSync(currentDir, { withFileTypes: true });
3997
+ return fs11__default.readdirSync(currentDir, { withFileTypes: true });
3860
3998
  } catch {
3861
3999
  return [];
3862
4000
  }
3863
4001
  })();
3864
4002
  for (const entry of entries) {
3865
- const fullPath = path3.join(currentDir, entry.name);
4003
+ const fullPath = path6__default.join(currentDir, entry.name);
3866
4004
  if (entry.isDirectory()) {
3867
4005
  if (!ignoreDirectories.has(entry.name)) directories.push(fullPath);
3868
4006
  continue;
3869
4007
  }
3870
4008
  if (!entry.isFile()) continue;
3871
- if (!extensionSet.has(path3.extname(entry.name))) continue;
4009
+ if (!extensionSet.has(path6__default.extname(entry.name))) continue;
3872
4010
  candidates.push(fullPath);
3873
4011
  }
3874
4012
  }
@@ -3882,9 +4020,12 @@ function toCacheSize(size) {
3882
4020
  function scanSource(source) {
3883
4021
  const nativeBinding = nativeParserLoader.get();
3884
4022
  if (nativeBinding?.extractClassesFromSource) {
3885
- const classes = nativeBinding.extractClassesFromSource(source);
3886
- if (Array.isArray(classes)) {
3887
- return Array.from(new Set(classes.filter(Boolean)));
4023
+ const result = nativeBinding.extractClassesFromSource(source);
4024
+ if (Array.isArray(result)) {
4025
+ return Array.from(new Set(result.filter(Boolean)));
4026
+ }
4027
+ if (result !== null && result !== void 0 && Array.isArray(result.classes)) {
4028
+ return Array.from(new Set(result.classes.filter(Boolean)));
3888
4029
  }
3889
4030
  }
3890
4031
  throw new Error(
@@ -3892,15 +4033,18 @@ function scanSource(source) {
3892
4033
  );
3893
4034
  }
3894
4035
  function isScannableFile(filePath, includeExtensions = DEFAULT_EXTENSIONS) {
3895
- return includeExtensions.includes(path3.extname(filePath));
4036
+ return includeExtensions.includes(path6__default.extname(filePath));
3896
4037
  }
3897
4038
  function scanFile(filePath) {
3898
- const source = fs8.readFileSync(filePath, "utf8");
3899
- const hash = hashContentNative(source) ?? void 0;
4039
+ const { scanFileNative: scanFileNative2 } = (init_native_bridge(), __toCommonJS(native_bridge_exports));
4040
+ const result = scanFileNative2(filePath);
4041
+ if (!result.ok) {
4042
+ throw new Error(`scanFile failed for ${filePath}: ${result.error ?? "unknown error"}`);
4043
+ }
3900
4044
  return {
3901
- file: filePath,
3902
- classes: scanSource(source),
3903
- ...hash ? { hash } : {}
4045
+ file: result.file,
4046
+ classes: result.classes,
4047
+ ...result.hash ? { hash: result.hash } : {}
3904
4048
  };
3905
4049
  }
3906
4050
  function scanWorkspace(rootDir, options = {}) {
@@ -3949,7 +4093,7 @@ function scanWorkspace(rootDir, options = {}) {
3949
4093
  for (const filePath of candidates) {
3950
4094
  const stat = (() => {
3951
4095
  try {
3952
- return fs8.statSync(filePath);
4096
+ return fs11__default.statSync(filePath);
3953
4097
  } catch {
3954
4098
  return null;
3955
4099
  }
@@ -3975,7 +4119,7 @@ function scanWorkspace(rootDir, options = {}) {
3975
4119
  for (const { filePath, stat, size, cached } of ranked) {
3976
4120
  const content = (() => {
3977
4121
  try {
3978
- return fs8.readFileSync(filePath, "utf8");
4122
+ return fs11__default.readFileSync(filePath, "utf8");
3979
4123
  } catch {
3980
4124
  return null;
3981
4125
  }
@@ -4037,14 +4181,21 @@ function scanWorkspace(rootDir, options = {}) {
4037
4181
  }
4038
4182
  async function scanWorkspaceAsync(rootDir, options = {}) {
4039
4183
  const normalizedOptions = parseScanWorkspaceOptions(options);
4040
- if (process.env.TWS_DISABLE_SCANNER_WORKER === "1") {
4041
- return scanWorkspace(rootDir, normalizedOptions);
4184
+ try {
4185
+ return await scanWorkspaceParallel(rootDir, {
4186
+ extensions: normalizedOptions.includeExtensions,
4187
+ ignoreDirs: normalizedOptions.ignoreDirectories
4188
+ });
4189
+ } catch (parallelError) {
4190
+ log2.debug(
4191
+ `parallel scan failed, retrying with single worker: ${parallelError instanceof Error ? parallelError.message : String(parallelError)}`
4192
+ );
4042
4193
  }
4043
4194
  try {
4044
4195
  return await scanWorkspaceInWorker(rootDir, normalizedOptions);
4045
4196
  } catch (error) {
4046
4197
  log2.debug(
4047
- `worker scan failed, falling back to sync scanner: ${error instanceof Error ? error.message : String(error)}`
4198
+ `worker scan failed, retrying with sync native scanner: ${error instanceof Error ? error.message : String(error)}`
4048
4199
  );
4049
4200
  return scanWorkspace(rootDir, normalizedOptions);
4050
4201
  }
@@ -4055,7 +4206,10 @@ var init_src2 = __esm({
4055
4206
  init_src();
4056
4207
  init_cache_native();
4057
4208
  init_native_bridge();
4209
+ init_parallel_scanner();
4058
4210
  init_schemas();
4211
+ init_schemas();
4212
+ init_native_bridge();
4059
4213
  log2 = createLogger("scanner");
4060
4214
  SCAN_WORKER_TIMEOUT_MS = 12e4;
4061
4215
  createNativeParserLoader = () => {
@@ -4069,12 +4223,25 @@ var init_src2 = __esm({
4069
4223
  const loadNativeParserBinding = () => {
4070
4224
  if (_state.binding !== void 0) return _state.binding;
4071
4225
  const runtimeDir = getRuntimeDir();
4072
- const req = createRequire(path3.join(runtimeDir, "noop.cjs"));
4226
+ const req = createRequire(path6__default.join(runtimeDir, "noop.cjs"));
4073
4227
  const candidates = [
4074
- path3.resolve(process.cwd(), "native/tailwind_styled_parser.node"),
4075
- path3.resolve(process.cwd(), "native/build/Release/tailwind_styled_parser.node"),
4076
- path3.resolve(runtimeDir, "..", "..", "..", "native", "tailwind_styled_parser.node"),
4077
- path3.resolve(
4228
+ // ── binaryName baru: tailwind-styled-native (napi-rs naming) ──
4229
+ // cwd = repo root saat run dari root, atau package dir saat workspaces
4230
+ path6__default.resolve(process.cwd(), "native", "tailwind-styled-native.node"),
4231
+ path6__default.resolve(process.cwd(), "native", `tailwind-styled-native.${process.platform}-${process.arch}.node`),
4232
+ path6__default.resolve(process.cwd(), "native", `tailwind-styled-native.${process.platform}-${process.arch}-gnu.node`),
4233
+ // runtimeDir = dist/ → naik 4 level ke repo root
4234
+ path6__default.resolve(runtimeDir, "..", "..", "..", "..", "native", "tailwind-styled-native.node"),
4235
+ path6__default.resolve(runtimeDir, "..", "..", "..", "..", "native", `tailwind-styled-native.${process.platform}-${process.arch}-gnu.node`),
4236
+ // 3 level fallback (jika package di-nest lebih dangkal)
4237
+ path6__default.resolve(runtimeDir, "..", "..", "..", "native", "tailwind-styled-native.node"),
4238
+ path6__default.resolve(runtimeDir, "..", "..", "..", "native", `tailwind-styled-native.${process.platform}-${process.arch}-gnu.node`),
4239
+ // ── binaryName lama: tailwind_styled_parser (backward compat) ──
4240
+ path6__default.resolve(process.cwd(), "native/tailwind_styled_parser.node"),
4241
+ path6__default.resolve(process.cwd(), "native/build/Release/tailwind_styled_parser.node"),
4242
+ path6__default.resolve(runtimeDir, "..", "..", "..", "..", "native", "tailwind_styled_parser.node"),
4243
+ path6__default.resolve(runtimeDir, "..", "..", "..", "native", "tailwind_styled_parser.node"),
4244
+ path6__default.resolve(
4078
4245
  runtimeDir,
4079
4246
  "..",
4080
4247
  "..",
@@ -4086,7 +4253,7 @@ var init_src2 = __esm({
4086
4253
  )
4087
4254
  ];
4088
4255
  for (const fullPath of candidates) {
4089
- if (!fs8.existsSync(fullPath)) continue;
4256
+ if (!fs11__default.existsSync(fullPath)) continue;
4090
4257
  try {
4091
4258
  const required = req(fullPath);
4092
4259
  if (required && (typeof required.extractClassesFromSource === "function" || typeof required.parseClasses === "function" || typeof required.parse_classes === "function")) {
@@ -4128,7 +4295,7 @@ function isRecord(value) {
4128
4295
  }
4129
4296
  async function pathExists(filePath) {
4130
4297
  try {
4131
- await fs8.promises.access(filePath, fs8.constants.F_OK);
4298
+ await fs11__default.promises.access(filePath, fs11__default.constants.F_OK);
4132
4299
  return true;
4133
4300
  } catch {
4134
4301
  return false;
@@ -4154,6 +4321,9 @@ var init_utils = __esm({
4154
4321
  });
4155
4322
 
4156
4323
  // packages/domain/analyzer/src/binding.ts
4324
+ async function getNativeBinding() {
4325
+ return analyzerBindingLoader.get();
4326
+ }
4157
4327
  async function requireNativeBinding() {
4158
4328
  const binding = await analyzerBindingLoader.get();
4159
4329
  if (binding?.analyzeClasses) return binding;
@@ -4246,7 +4416,7 @@ var formatIssuePath3, isPlainObject, formatIssues2, parseWithSchema2, CountSchem
4246
4416
  var init_schemas2 = __esm({
4247
4417
  "packages/domain/analyzer/src/schemas.ts"() {
4248
4418
  init_src();
4249
- formatIssuePath3 = (path26) => path26.length > 0 ? path26.map(
4419
+ formatIssuePath3 = (path29) => path29.length > 0 ? path29.map(
4250
4420
  (segment) => typeof segment === "symbol" ? segment.description ?? segment.toString() : String(segment)
4251
4421
  ).join(".") : "<root>";
4252
4422
  isPlainObject = (value) => {
@@ -4255,8 +4425,8 @@ var init_schemas2 = __esm({
4255
4425
  return proto === Object.prototype || proto === null;
4256
4426
  };
4257
4427
  formatIssues2 = (error) => error.issues.map((issue) => {
4258
- const path26 = formatIssuePath3(issue.path);
4259
- return `${path26}: ${issue.message}`;
4428
+ const path29 = formatIssuePath3(issue.path);
4429
+ return `${path29}: ${issue.message}`;
4260
4430
  }).join("; ");
4261
4431
  parseWithSchema2 = (schema, data, label) => {
4262
4432
  const parsed = schema.safeParse(data);
@@ -4352,117 +4522,12 @@ var init_schemas2 = __esm({
4352
4522
  parseClassToCssOptions = (options) => parseWithSchema2(ClassToCssOptionsSchema, options ?? {}, "classToCss options are invalid");
4353
4523
  }
4354
4524
  });
4355
- var SUPPORTED_TAILWIND_CONFIG_EXTENSIONS, KNOWN_UTILITY_PREFIXES, tailwindConfigCache, splitVariantAndBase, isArbitraryUtility, resolveConflictGroup, detectConflicts, isSupportedTailwindConfigPath, resolveTailwindConfigPath, collectSafelistFromConfig, collectCustomUtilities, collectSafelistFromSource, loadTailwindConfig, utilityPrefix, isKnownTailwindClass, buildSemanticReport;
4525
+ var SUPPORTED_TAILWIND_CONFIG_EXTENSIONS, tailwindConfigCache, splitVariantAndBase, isArbitraryUtility, resolveConflictGroup, detectConflicts, isSupportedTailwindConfigPath, resolveTailwindConfigPath, collectSafelistFromConfig, collectCustomUtilities, collectSafelistFromSource, loadTailwindConfig, utilityPrefix, buildSemanticReport;
4356
4526
  var init_semantic = __esm({
4357
4527
  "packages/domain/analyzer/src/semantic.ts"() {
4528
+ init_binding();
4358
4529
  init_utils();
4359
4530
  SUPPORTED_TAILWIND_CONFIG_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".js", ".cjs", ".mjs"]);
4360
- KNOWN_UTILITY_PREFIXES = /* @__PURE__ */ new Set([
4361
- "absolute",
4362
- "align",
4363
- "animate",
4364
- "arbitrary",
4365
- "aspect",
4366
- "backdrop",
4367
- "basis",
4368
- "bg",
4369
- "block",
4370
- "border",
4371
- "bottom",
4372
- "col",
4373
- "container",
4374
- "contents",
4375
- "cursor",
4376
- "dark",
4377
- "display",
4378
- "divide",
4379
- "fill",
4380
- "fixed",
4381
- "flex",
4382
- "float",
4383
- "font",
4384
- "from",
4385
- "gap",
4386
- "grid",
4387
- "grow",
4388
- "h",
4389
- "hidden",
4390
- "inset",
4391
- "inline",
4392
- "isolate",
4393
- "items",
4394
- "justify",
4395
- "left",
4396
- "leading",
4397
- "line",
4398
- "list",
4399
- "m",
4400
- "max-h",
4401
- "max-w",
4402
- "mb",
4403
- "min-h",
4404
- "min-w",
4405
- "ml",
4406
- "mr",
4407
- "mt",
4408
- "mx",
4409
- "my",
4410
- "object",
4411
- "opacity",
4412
- "order",
4413
- "origin",
4414
- "outline",
4415
- "overflow",
4416
- "overscroll",
4417
- "p",
4418
- "pb",
4419
- "pe",
4420
- "perspective",
4421
- "place",
4422
- "pl",
4423
- "pointer",
4424
- "position",
4425
- "pr",
4426
- "ps",
4427
- "pt",
4428
- "px",
4429
- "py",
4430
- "relative",
4431
- "right",
4432
- "ring",
4433
- "rotate",
4434
- "rounded",
4435
- "row",
4436
- "scale",
4437
- "shadow",
4438
- "shrink",
4439
- "size",
4440
- "skew",
4441
- "snap",
4442
- "space-x",
4443
- "space-y",
4444
- "sr",
4445
- "start",
4446
- "static",
4447
- "sticky",
4448
- "stroke",
4449
- "table",
4450
- "text",
4451
- "to",
4452
- "top",
4453
- "touch",
4454
- "tracking",
4455
- "transform",
4456
- "transition",
4457
- "translate",
4458
- "truncate",
4459
- "underline",
4460
- "via",
4461
- "visible",
4462
- "w",
4463
- "whitespace",
4464
- "z"
4465
- ]);
4466
4531
  tailwindConfigCache = /* @__PURE__ */ new Map();
4467
4532
  splitVariantAndBase = (className) => {
4468
4533
  const parts = className.split(":");
@@ -4492,48 +4557,28 @@ var init_semantic = __esm({
4492
4557
  if (base.startsWith("m-") || base.startsWith("mx-") || base.startsWith("my-")) return "margin";
4493
4558
  return null;
4494
4559
  };
4495
- detectConflicts = (usages) => {
4496
- const buckets = /* @__PURE__ */ new Map();
4497
- for (const usage of usages) {
4498
- const { variantKey, base } = splitVariantAndBase(usage.name);
4499
- const group = resolveConflictGroup(base);
4500
- if (!group) continue;
4501
- const key = `${variantKey}::${group}`;
4502
- const bucket = buckets.get(key) ?? {
4503
- variantKey,
4504
- group,
4505
- classes: /* @__PURE__ */ new Set()
4506
- };
4507
- bucket.classes.add(usage.name);
4508
- buckets.set(key, bucket);
4509
- }
4510
- const conflicts = [];
4511
- const conflictedClassNames = /* @__PURE__ */ new Set();
4512
- for (const bucket of buckets.values()) {
4513
- if (bucket.classes.size <= 1) continue;
4514
- const classes = Array.from(bucket.classes).sort();
4515
- for (const className of classes) conflictedClassNames.add(className);
4516
- const variantLabel = bucket.variantKey.length > 0 ? bucket.variantKey : "base";
4517
- conflicts.push({
4518
- className: bucket.group,
4519
- variants: bucket.variantKey.length > 0 ? bucket.variantKey.split(":") : [],
4520
- classes,
4521
- message: `Multiple ${bucket.group} utilities detected for "${variantLabel}".`
4522
- });
4560
+ detectConflicts = async (usages) => {
4561
+ const native = await getNativeBinding();
4562
+ if (!native?.detectClassConflicts) {
4563
+ throw new Error("FATAL: Native binding 'detectClassConflicts' is required but not available.");
4523
4564
  }
4524
- conflicts.sort((left, right) => {
4525
- if (right.classes.length !== left.classes.length)
4526
- return right.classes.length - left.classes.length;
4527
- return left.className.localeCompare(right.className);
4528
- });
4529
- return { conflicts, conflictedClassNames };
4565
+ const result = native.detectClassConflicts(JSON.stringify(usages.map((u) => ({ name: u.name, count: u.count }))));
4566
+ return {
4567
+ conflicts: result.conflicts.map((c) => ({
4568
+ className: c.group,
4569
+ variants: c.variantKey.length > 0 ? c.variantKey.split(":") : [],
4570
+ classes: c.classes,
4571
+ message: c.message
4572
+ })),
4573
+ conflictedClassNames: new Set(result.conflictedClassNames)
4574
+ };
4530
4575
  };
4531
4576
  isSupportedTailwindConfigPath = (configPath) => {
4532
- return SUPPORTED_TAILWIND_CONFIG_EXTENSIONS.has(path3.extname(configPath).toLowerCase());
4577
+ return SUPPORTED_TAILWIND_CONFIG_EXTENSIONS.has(path6__default.extname(configPath).toLowerCase());
4533
4578
  };
4534
4579
  resolveTailwindConfigPath = async (root, explicitPath) => {
4535
4580
  if (explicitPath) {
4536
- const resolved = path3.resolve(root, explicitPath);
4581
+ const resolved = path6__default.resolve(root, explicitPath);
4537
4582
  if (!await pathExists(resolved)) return null;
4538
4583
  return resolved;
4539
4584
  }
@@ -4544,7 +4589,7 @@ var init_semantic = __esm({
4544
4589
  "tailwind.config.mjs"
4545
4590
  ];
4546
4591
  for (const candidate of candidates) {
4547
- const fullPath = path3.resolve(root, candidate);
4592
+ const fullPath = path6__default.resolve(root, candidate);
4548
4593
  if (await pathExists(fullPath)) return fullPath;
4549
4594
  }
4550
4595
  return null;
@@ -4598,15 +4643,19 @@ var init_semantic = __esm({
4598
4643
  return out;
4599
4644
  };
4600
4645
  collectSafelistFromSource = async (configPath) => {
4601
- const source = await fs8.promises.readFile(configPath, "utf8");
4602
- const safelistBlock = source.match(/safelist\s*:\s*\[([\s\S]*?)\]/m)?.[1];
4603
- if (!safelistBlock) return [];
4604
- const out = /* @__PURE__ */ new Set();
4605
- for (const token of safelistBlock.matchAll(/["'`]([^"'`]+)["'`]/g)) {
4646
+ const source = await fs11__default.promises.readFile(configPath, "utf8");
4647
+ const { extractClassesNative: extractClassesNative2 } = await Promise.resolve().then(() => (init_src2(), src_exports));
4648
+ const allTokens = extractClassesNative2(source);
4649
+ const hasSafelist = source.includes("safelist");
4650
+ if (!hasSafelist) return [];
4651
+ const safelistMatch = source.match(/safelist\s*:\s*\[([\s\S]*?)\]/m)?.[1];
4652
+ if (!safelistMatch) return [];
4653
+ const safelistSet = /* @__PURE__ */ new Set();
4654
+ for (const token of safelistMatch.matchAll(/["'`]([^"'`]+)["'`]/g)) {
4606
4655
  const value = token[1].trim();
4607
- if (value.length > 0) out.add(value);
4656
+ if (value.length > 0) safelistSet.add(value);
4608
4657
  }
4609
- return Array.from(out);
4658
+ return allTokens.filter((t) => safelistSet.has(t));
4610
4659
  };
4611
4660
  loadTailwindConfig = async (root, semanticOption) => {
4612
4661
  const startMs = Date.now();
@@ -4621,7 +4670,7 @@ var init_semantic = __esm({
4621
4670
  customUtilities: /* @__PURE__ */ new Set()
4622
4671
  };
4623
4672
  }
4624
- const configStat = await fs8.promises.stat(configPath).catch(() => null);
4673
+ const configStat = await fs11__default.promises.stat(configPath).catch(() => null);
4625
4674
  if (configStat) {
4626
4675
  const cached = tailwindConfigCache.get(configPath);
4627
4676
  if (cached && cached.mtimeMs === configStat.mtimeMs && cached.size === configStat.size) {
@@ -4707,21 +4756,27 @@ var init_semantic = __esm({
4707
4756
  if (hyphen < 0) return normalized;
4708
4757
  return normalized.slice(0, hyphen);
4709
4758
  };
4710
- isKnownTailwindClass = (className, safelist, customUtilities) => {
4711
- if (safelist.has(className) || customUtilities.has(className)) return true;
4712
- const { base } = splitVariantAndBase(className);
4713
- if (customUtilities.has(base)) return true;
4714
- const prefix = utilityPrefix(base);
4715
- return KNOWN_UTILITY_PREFIXES.has(prefix);
4716
- };
4717
4759
  buildSemanticReport = async (usages, root, semanticOption) => {
4718
4760
  const loadedConfig = await loadTailwindConfig(root, semanticOption);
4719
4761
  const safelist = loadedConfig?.safelist ?? /* @__PURE__ */ new Set();
4720
4762
  const customUtilities = loadedConfig?.customUtilities ?? /* @__PURE__ */ new Set();
4721
4763
  const usageNames = new Set(usages.map((usage) => usage.name));
4722
4764
  const unusedClasses = Array.from(safelist).filter((className) => !usageNames.has(className)).sort().map((className) => ({ name: className, count: 0, isUnused: true }));
4723
- const unknownClasses = usages.filter((usage) => !isKnownTailwindClass(usage.name, safelist, customUtilities)).map((usage) => ({ ...usage, isUnused: true }));
4724
- const { conflicts } = detectConflicts(usages);
4765
+ const native = await getNativeBinding();
4766
+ if (!native?.classifyKnownClasses) {
4767
+ throw new Error("FATAL: Native binding 'classifyKnownClasses' is required but not available.");
4768
+ }
4769
+ const classNames = usages.map((u) => u.name);
4770
+ const results = native.classifyKnownClasses(
4771
+ classNames,
4772
+ Array.from(safelist),
4773
+ Array.from(customUtilities)
4774
+ );
4775
+ const unknownSet = new Set(
4776
+ results.filter((r) => !r.isKnown).map((r) => r.className)
4777
+ );
4778
+ const unknownClasses = usages.filter((usage) => unknownSet.has(usage.name)).map((usage) => ({ ...usage, isUnused: true }));
4779
+ const { conflicts } = await detectConflicts(usages);
4725
4780
  return {
4726
4781
  unusedClasses,
4727
4782
  unknownClasses,
@@ -4757,13 +4812,17 @@ function normalizeScan(scan, includeClass) {
4757
4812
  uniqueClasses: Array.from(unique).sort()
4758
4813
  };
4759
4814
  }
4760
- function collectClassCounts(scan) {
4761
- const counts = /* @__PURE__ */ new Map();
4762
- for (const file of scan.files) {
4763
- for (const className of file.classes) {
4764
- counts.set(className, (counts.get(className) ?? 0) + 1);
4765
- }
4815
+ async function collectClassCounts(scan) {
4816
+ const native = await requireNativeBinding();
4817
+ if (!native?.collectClassCounts) {
4818
+ throw new Error("FATAL: Native binding 'collectClassCounts' is required but not available.");
4766
4819
  }
4820
+ const filesJson = JSON.stringify(
4821
+ scan.files.map((f) => ({ file: f.file ?? "", classes: f.classes }))
4822
+ );
4823
+ const result = native.collectClassCounts(filesJson);
4824
+ const counts = /* @__PURE__ */ new Map();
4825
+ for (const entry of result) counts.set(entry.name, entry.count);
4767
4826
  return counts;
4768
4827
  }
4769
4828
  function buildClassUsage(counts) {
@@ -4772,29 +4831,24 @@ function buildClassUsage(counts) {
4772
4831
  return left.name.localeCompare(right.name);
4773
4832
  });
4774
4833
  }
4775
- function buildDistribution(usages) {
4776
- const distribution = {
4777
- "1": 0,
4778
- "2-3": 0,
4779
- "4-7": 0,
4780
- "8+": 0
4781
- };
4782
- for (const usage of usages) {
4783
- if (usage.count === 1) {
4784
- distribution["1"] += 1;
4785
- } else if (usage.count <= 3) {
4786
- distribution["2-3"] += 1;
4787
- } else if (usage.count <= 7) {
4788
- distribution["4-7"] += 1;
4789
- } else {
4790
- distribution["8+"] += 1;
4791
- }
4834
+ async function buildDistribution(usages, native) {
4835
+ const binding = native ?? await requireNativeBinding();
4836
+ if (!binding?.buildDistribution) {
4837
+ throw new Error("FATAL: Native binding 'buildDistribution' is required but not available.");
4792
4838
  }
4793
- return distribution;
4839
+ const result = binding.buildDistribution(
4840
+ JSON.stringify(usages.map((u) => ({ name: u.name, count: u.count })))
4841
+ );
4842
+ return {
4843
+ "1": result.once,
4844
+ "2-3": result.few,
4845
+ "4-7": result.moderate,
4846
+ "8+": result.frequent
4847
+ };
4794
4848
  }
4795
4849
  async function analyzeWorkspace(root, options = {}) {
4796
4850
  const startedAtMs = Date.now();
4797
- const resolvedRoot = path3.resolve(root);
4851
+ const resolvedRoot = path6__default.resolve(root);
4798
4852
  const normalizedOptions = parseAnalyzerOptions(options);
4799
4853
  const scan = await (async () => {
4800
4854
  const scanStartedAtMs = Date.now();
@@ -4838,7 +4892,7 @@ async function analyzeWorkspace(root, options = {}) {
4838
4892
  );
4839
4893
  }
4840
4894
  })();
4841
- const counts = collectClassCounts(normalizedScan);
4895
+ const counts = await collectClassCounts(normalizedScan);
4842
4896
  const baseAll = buildClassUsage(counts);
4843
4897
  const { all, semanticReport } = await (async () => {
4844
4898
  if (!normalizedOptions.semantic) {
@@ -4864,13 +4918,19 @@ async function analyzeWorkspace(root, options = {}) {
4864
4918
  );
4865
4919
  }
4866
4920
  })();
4867
- const top = all.slice(0, topLimit);
4868
- const frequent = all.filter((usage) => usage.count >= frequentThreshold).slice(0, topLimit);
4869
- const unique = all.filter((usage) => usage.count === 1);
4870
- const totalClassOccurrences = all.reduce((sum, usage) => sum + usage.count, 0);
4921
+ const classStatsNative = binding?.computeClassStats?.(
4922
+ JSON.stringify(all),
4923
+ topLimit,
4924
+ frequentThreshold
4925
+ );
4926
+ const top = classStatsNative ? JSON.parse(classStatsNative.topJson) : all.slice(0, topLimit);
4927
+ const frequent = classStatsNative ? JSON.parse(classStatsNative.frequentJson) : all.filter((usage) => usage.count >= frequentThreshold).slice(0, topLimit);
4928
+ const unique = classStatsNative ? JSON.parse(classStatsNative.uniqueJson) : all.filter((usage) => usage.count === 1);
4929
+ const totalClassOccurrences = classStatsNative ? classStatsNative.totalClassOccurrences : all.reduce((sum, usage) => sum + usage.count, 0);
4871
4930
  debugLog(
4872
4931
  `analyzeWorkspace completed in ${Date.now() - startedAtMs}ms (files=${normalizedScan.totalFiles}, uniqueClasses=${all.length})`
4873
4932
  );
4933
+ const distribution = await buildDistribution(all, binding);
4874
4934
  return {
4875
4935
  root: nativeReport.root || resolvedRoot,
4876
4936
  totalFiles: nativeReport.totalFiles,
@@ -4881,8 +4941,10 @@ async function analyzeWorkspace(root, options = {}) {
4881
4941
  top,
4882
4942
  frequent,
4883
4943
  unique,
4884
- distribution: buildDistribution(all)
4944
+ distribution
4885
4945
  },
4946
+ // topClasses — alias for classStats.top (test contract & backward compat)
4947
+ topClasses: top,
4886
4948
  safelist: all.map((usage) => usage.name),
4887
4949
  ...semanticReport ? { semantic: semanticReport } : {}
4888
4950
  };
@@ -4904,8 +4966,11 @@ var init_classToCss = __esm({
4904
4966
  init_binding();
4905
4967
  init_schemas2();
4906
4968
  init_utils();
4907
- normalizeClassInput = (input) => {
4969
+ normalizeClassInput = (input, _binding) => {
4908
4970
  if (typeof input === "string") {
4971
+ if (_binding?.normalizeClassInput) {
4972
+ return _binding.normalizeClassInput(input);
4973
+ }
4909
4974
  return input.split(/\s+/).map((item) => item.trim()).filter((item) => item.length > 0);
4910
4975
  }
4911
4976
  if (!Array.isArray(input)) {
@@ -4927,27 +4992,26 @@ var init_classToCss = __esm({
4927
4992
  const prefix = parsed.prefix ?? null;
4928
4993
  return { prefix, strict };
4929
4994
  };
4930
- mergeDeclarationMap = (target, css) => {
4931
- for (const ruleMatch of css.matchAll(/\{([^}]*)\}/g)) {
4932
- const body = ruleMatch[1];
4933
- for (const raw of body.split(";")) {
4934
- const declaration = raw.trim();
4935
- if (declaration.length === 0) continue;
4936
- const colonIndex = declaration.indexOf(":");
4937
- if (colonIndex <= 0) continue;
4938
- const property = declaration.slice(0, colonIndex).trim();
4939
- const value = declaration.slice(colonIndex + 1).trim();
4940
- if (property.length === 0 || value.length === 0) continue;
4941
- if (target.has(property)) target.delete(property);
4942
- target.set(property, value);
4943
- }
4995
+ mergeDeclarationMap = (target, css, binding) => {
4996
+ if (!binding.parseCssRules) {
4997
+ throw new Error("FATAL: Native binding 'parseCssRules' is required but not available.");
4998
+ }
4999
+ const rules = binding.parseCssRules(css);
5000
+ for (const rule of rules) {
5001
+ if (target.has(rule.property)) target.delete(rule.property);
5002
+ target.set(rule.property, rule.isImportant ? `${rule.value} !important` : rule.value);
4944
5003
  }
4945
5004
  };
4946
- declarationMapToString = (declarationMap) => {
4947
- return Array.from(declarationMap.entries()).map(([property, value]) => `${property}: ${value}`).join("; ");
5005
+ declarationMapToString = (declarationMap, binding) => {
5006
+ const entries = Array.from(declarationMap.entries()).map(([property, value]) => ({ property, value }));
5007
+ if (binding?.declarationMapToString) {
5008
+ return binding.declarationMapToString(entries);
5009
+ }
5010
+ return entries.map(({ property, value }) => `${property}: ${value}`).join("; ");
4948
5011
  };
4949
5012
  classToCss = async (input, options = {}) => {
4950
- const inputClasses = normalizeClassInput(input);
5013
+ const binding = await requireNativeCssCompiler();
5014
+ const inputClasses = normalizeClassInput(input, binding);
4951
5015
  const normalizedOptions = normalizeClassToCssOptions(options);
4952
5016
  if (inputClasses.length === 0) {
4953
5017
  return {
@@ -4959,7 +5023,6 @@ var init_classToCss = __esm({
4959
5023
  sizeBytes: 0
4960
5024
  };
4961
5025
  }
4962
- const binding = await requireNativeCssCompiler();
4963
5026
  const prefix = normalizedOptions.prefix;
4964
5027
  const results = await Promise.all(
4965
5028
  inputClasses.map(async (className) => {
@@ -4992,7 +5055,7 @@ var init_classToCss = __esm({
4992
5055
  const sizeBytes = results.reduce((sum, r) => sum + r.sizeBytes, 0);
4993
5056
  const declarationMap = /* @__PURE__ */ new Map();
4994
5057
  for (const result of results) {
4995
- mergeDeclarationMap(declarationMap, result.css);
5058
+ mergeDeclarationMap(declarationMap, result.css, binding);
4996
5059
  }
4997
5060
  const uniqueUnknown = Array.from(new Set(unknownClasses));
4998
5061
  if (normalizedOptions.strict && uniqueUnknown.length > 0) {
@@ -5001,7 +5064,7 @@ var init_classToCss = __esm({
5001
5064
  return {
5002
5065
  inputClasses,
5003
5066
  css: cssChunks.filter((chunk) => chunk.length > 0).join("\n"),
5004
- declarations: declarationMapToString(declarationMap),
5067
+ declarations: declarationMapToString(declarationMap, binding),
5005
5068
  resolvedClasses: Array.from(new Set(resolvedClasses)),
5006
5069
  unknownClasses: uniqueUnknown,
5007
5070
  sizeBytes
@@ -5011,8 +5074,8 @@ var init_classToCss = __esm({
5011
5074
  });
5012
5075
 
5013
5076
  // packages/domain/analyzer/src/index.ts
5014
- var src_exports = {};
5015
- __export(src_exports, {
5077
+ var src_exports2 = {};
5078
+ __export(src_exports2, {
5016
5079
  __internal: () => __internal,
5017
5080
  analyzeWorkspace: () => analyzeWorkspace,
5018
5081
  classToCss: () => classToCss
@@ -5040,7 +5103,7 @@ var init_src3 = __esm({
5040
5103
  });
5041
5104
  async function pathExists2(filePath) {
5042
5105
  try {
5043
- await fs4.access(filePath);
5106
+ await fs7.access(filePath);
5044
5107
  return true;
5045
5108
  } catch {
5046
5109
  return false;
@@ -5048,7 +5111,7 @@ async function pathExists2(filePath) {
5048
5111
  }
5049
5112
  async function readFileSafe(filePath) {
5050
5113
  try {
5051
- return await fs4.readFile(filePath, "utf8");
5114
+ return await fs7.readFile(filePath, "utf8");
5052
5115
  } catch {
5053
5116
  return null;
5054
5117
  }
@@ -5067,8 +5130,8 @@ async function writeFileSafe(filePath, content, options = {}) {
5067
5130
  options.onDryRun?.(`write ${filePath}`);
5068
5131
  return;
5069
5132
  }
5070
- await fs4.mkdir(path3.dirname(filePath), { recursive: true });
5071
- await fs4.writeFile(filePath, content, "utf8");
5133
+ await fs7.mkdir(path6__default.dirname(filePath), { recursive: true });
5134
+ await fs7.writeFile(filePath, content, "utf8");
5072
5135
  }
5073
5136
  async function ensureFileSafe(filePath, content, options = {}) {
5074
5137
  if (await pathExists2(filePath)) return "skipped";
@@ -5356,11 +5419,11 @@ var init_args = __esm({
5356
5419
  });
5357
5420
  function runtimeDirFromImportMeta(importMetaUrl) {
5358
5421
  const filename = fileURLToPath(importMetaUrl);
5359
- return path3.dirname(filename);
5422
+ return path6__default.dirname(filename);
5360
5423
  }
5361
5424
  async function resolveMonorepoPath(runtimeDir, relativeToRepoRoot) {
5362
- const fromRuntime = path3.resolve(runtimeDir, "..", "..", "..", relativeToRepoRoot);
5363
- const fromCwd = path3.resolve(process.cwd(), relativeToRepoRoot);
5425
+ const fromRuntime = path6__default.resolve(runtimeDir, "..", "..", "..", relativeToRepoRoot);
5426
+ const fromCwd = path6__default.resolve(process.cwd(), relativeToRepoRoot);
5364
5427
  return await pathExists2(fromRuntime) ? fromRuntime : fromCwd;
5365
5428
  }
5366
5429
  async function firstExistingPath(paths) {
@@ -5436,7 +5499,8 @@ async function runCliMain(options) {
5436
5499
  await program2.parseAsync(argv);
5437
5500
  } catch (error) {
5438
5501
  const isHelpError = isHelpExit(error);
5439
- if (isHelpError) return;
5502
+ const isVersionError = isVersionExit(error);
5503
+ if (isHelpError || isVersionError) return;
5440
5504
  const normalized = normalizeCliError(error);
5441
5505
  const isJson = input.json;
5442
5506
  if (isJson) {
@@ -5451,7 +5515,7 @@ async function runCliMain(options) {
5451
5515
  process.exitCode = errorExitCode(normalized);
5452
5516
  }
5453
5517
  }
5454
- var isCommanderLikeError, isHelpExit, normalizeCliError, findCommandByPath, resolveCommandHelp, resolveHelpPath, walkCommands;
5518
+ var isCommanderLikeError, isHelpExit, isVersionExit, normalizeCliError, findCommandByPath, resolveCommandHelp, resolveHelpPath, walkCommands;
5455
5519
  var init_runtime = __esm({
5456
5520
  "packages/infrastructure/cli/src/utils/runtime.ts"() {
5457
5521
  init_args();
@@ -5464,6 +5528,9 @@ var init_runtime = __esm({
5464
5528
  isHelpExit = (error) => {
5465
5529
  return isCommanderLikeError(error) && error.code === "commander.helpDisplayed";
5466
5530
  };
5531
+ isVersionExit = (error) => {
5532
+ return isCommanderLikeError(error) && error.code === "commander.version";
5533
+ };
5467
5534
  normalizeCliError = (error) => {
5468
5535
  if (!isCommanderLikeError(error)) return error;
5469
5536
  if (!error.code?.startsWith("commander.")) return error;
@@ -5544,7 +5611,7 @@ async function resolveCreateInput(options) {
5544
5611
  return { name: resolvedName, template: templateValue };
5545
5612
  }
5546
5613
  async function writeProjectFile(context, relativePath, content) {
5547
- const filePath = path3.join(context.projectDir, relativePath);
5614
+ const filePath = path6__default.join(context.projectDir, relativePath);
5548
5615
  await writeFileSafe(filePath, content, { dryRun: context.dryRun });
5549
5616
  context.writtenFiles.push(relativePath.replaceAll("\\", "/"));
5550
5617
  }
@@ -5663,7 +5730,6 @@ async function createViteVueApp(context) {
5663
5730
  scripts: { dev: "vite", build: "vite build", preview: "vite preview" },
5664
5731
  dependencies: {
5665
5732
  vue: "^3.4.0",
5666
- "tailwind-merge": "^3.5.0",
5667
5733
  "tailwind-styled-v4/vue": "^5.0.0"
5668
5734
  },
5669
5735
  devDependencies: {
@@ -5760,7 +5826,7 @@ async function createViteSvelteApp(context) {
5760
5826
  private: true,
5761
5827
  type: "module",
5762
5828
  scripts: { dev: "vite", build: "vite build", preview: "vite preview" },
5763
- dependencies: { "tailwind-merge": "^3.5.0", "tailwind-styled-v4/svelte": "^5.0.0" },
5829
+ dependencies: { "tailwind-styled-v4/svelte": "^5.0.0" },
5764
5830
  devDependencies: {
5765
5831
  svelte: "^5.0.0",
5766
5832
  "@sveltejs/vite-plugin-svelte": "^3.0.0",
@@ -5861,7 +5927,7 @@ async function createSimpleApp(context) {
5861
5927
  }
5862
5928
  async function createProject(options, output) {
5863
5929
  const { name, template } = await resolveCreateInput(options);
5864
- const projectDir = path3.resolve(process.cwd(), name);
5930
+ const projectDir = path6__default.resolve(process.cwd(), name);
5865
5931
  if (await pathExists2(projectDir)) {
5866
5932
  throw new CliUsageError(`Directory ${name} already exists.`);
5867
5933
  }
@@ -5932,10 +5998,13 @@ var init_createApp = __esm({
5932
5998
  };
5933
5999
  }
5934
6000
  });
5935
- var log3, NATIVE_UNAVAILABLE_MESSAGE, nativeBridge, bridgeLoadAttempted, bridgeLoadError, isValidNativeBridge, getNativeBridge;
6001
+
6002
+ // packages/domain/compiler/src/nativeBridge.ts
6003
+ var _loadNative, log3, NATIVE_UNAVAILABLE_MESSAGE, nativeBridge, bridgeLoadAttempted, bridgeLoadError, isValidNativeBridge, getNativeBridge;
5936
6004
  var init_nativeBridge = __esm({
5937
6005
  "packages/domain/compiler/src/nativeBridge.ts"() {
5938
6006
  init_src();
6007
+ _loadNative = (path29) => __require(path29);
5939
6008
  log3 = (...args) => {
5940
6009
  if (process.env.DEBUG?.includes("compiler:native")) {
5941
6010
  console.log("[compiler:native]", ...args);
@@ -5962,11 +6031,10 @@ var init_nativeBridge = __esm({
5962
6031
  bridgeLoadAttempted = true;
5963
6032
  try {
5964
6033
  const runtimeDir = resolveRuntimeDir(void 0, import.meta.url);
5965
- const require2 = createRequire(import.meta.url);
5966
6034
  const result = resolveNativeBinary(runtimeDir);
5967
6035
  if (result.path && result.path.endsWith(".node")) {
5968
6036
  try {
5969
- const binding = require2(result.path);
6037
+ const binding = _loadNative(result.path);
5970
6038
  if (isValidNativeBridge(binding)) {
5971
6039
  nativeBridge = binding;
5972
6040
  log3("Native bridge loaded successfully from:", result.path);
@@ -6001,7 +6069,7 @@ init_esm();
6001
6069
  init_errors();
6002
6070
  async function loadAnalyzerModule() {
6003
6071
  try {
6004
- const mod = await Promise.resolve().then(() => (init_src3(), src_exports));
6072
+ const mod = await Promise.resolve().then(() => (init_src3(), src_exports2));
6005
6073
  if (typeof mod.analyzeWorkspace !== "function") {
6006
6074
  throw new Error("analyzeWorkspace export not found");
6007
6075
  }
@@ -6068,7 +6136,7 @@ async function runAnalyzeCli(args) {
6068
6136
  verbose: process.env.TWS_VERBOSE === "1" || process.env.VERBOSE === "1"
6069
6137
  });
6070
6138
  const dirArg = parsed.positionals[0] ?? ".";
6071
- const dir = path3.resolve(process.cwd(), dirArg);
6139
+ const dir = path6__default.resolve(process.cwd(), dirArg);
6072
6140
  if (!await pathExists2(dir)) {
6073
6141
  throw new CliUsageError(`Directory not found: ${dir}`);
6074
6142
  }
@@ -6124,7 +6192,7 @@ async function runExtractCli(args) {
6124
6192
  const parsedMin = parseInt(minRaw, 10);
6125
6193
  const minCount = Number.isFinite(parsedMin) && parsedMin > 0 ? parsedMin : 2;
6126
6194
  const dirArg = parsed.positionals[0] ?? ".";
6127
- const dir = path3.resolve(process.cwd(), dirArg);
6195
+ const dir = path6__default.resolve(process.cwd(), dirArg);
6128
6196
  if (!await pathExists2(dir)) {
6129
6197
  throw new CliUsageError(`Directory not found: ${dir}`);
6130
6198
  }
@@ -6197,15 +6265,15 @@ async function runInitCli(rawArgs) {
6197
6265
  verbose: process.env.TWS_VERBOSE === "1" || process.env.VERBOSE === "1"
6198
6266
  });
6199
6267
  const target = rawArgs.find((arg) => !arg.startsWith("-")) ?? ".";
6200
- const root = path3.resolve(process.cwd(), target);
6268
+ const root = path6__default.resolve(process.cwd(), target);
6201
6269
  const report = { created: [], skipped: [] };
6202
6270
  await ensureFile(
6203
- path3.join(root, "src", "tailwind.css"),
6271
+ path6__default.join(root, "src", "tailwind.css"),
6204
6272
  '@import "tailwindcss";\n\n@theme {\n --color-primary: #3b82f6;\n --spacing-section: 3rem;\n}\n',
6205
6273
  report
6206
6274
  );
6207
6275
  await ensureFile(
6208
- path3.join(root, "tailwind-styled.config.json"),
6276
+ path6__default.join(root, "tailwind-styled.config.json"),
6209
6277
  `${JSON.stringify(
6210
6278
  {
6211
6279
  version: 1,
@@ -6224,12 +6292,12 @@ async function runInitCli(rawArgs) {
6224
6292
  output.writeText("\nInit complete");
6225
6293
  output.writeText(`Created: ${report.created.length}`);
6226
6294
  for (const filePath of report.created) {
6227
- output.writeText(` + ${path3.relative(root, filePath)}`);
6295
+ output.writeText(` + ${path6__default.relative(root, filePath)}`);
6228
6296
  }
6229
6297
  if (report.skipped.length > 0) {
6230
6298
  output.writeText(`Skipped: ${report.skipped.length}`);
6231
6299
  for (const filePath of report.skipped) {
6232
- output.writeText(` - ${path3.relative(root, filePath)} (exists)`);
6300
+ output.writeText(` - ${path6__default.relative(root, filePath)} (exists)`);
6233
6301
  }
6234
6302
  }
6235
6303
  }
@@ -6290,15 +6358,15 @@ async function findSourceFiles(dir) {
6290
6358
  const out = [];
6291
6359
  async function walk(currentDir) {
6292
6360
  if (!await pathExists2(currentDir)) return;
6293
- const entries = await fs4.readdir(currentDir, { withFileTypes: true });
6361
+ const entries = await fs7.readdir(currentDir, { withFileTypes: true });
6294
6362
  for (const entry of entries) {
6295
- const fullPath = path3.join(currentDir, entry.name);
6363
+ const fullPath = path6__default.join(currentDir, entry.name);
6296
6364
  if (entry.isDirectory()) {
6297
6365
  if (IGNORED_DIRS.has(entry.name)) continue;
6298
6366
  await walk(fullPath);
6299
6367
  continue;
6300
6368
  }
6301
- if (SOURCE_EXTENSIONS.has(path3.extname(entry.name))) {
6369
+ if (SOURCE_EXTENSIONS.has(path6__default.extname(entry.name))) {
6302
6370
  out.push(fullPath);
6303
6371
  }
6304
6372
  }
@@ -6319,7 +6387,7 @@ function migrateSource(source, options) {
6319
6387
  return { output, classRenames: 0, importRenames };
6320
6388
  }
6321
6389
  async function migrateConfig(root, dryRun) {
6322
- const cssPath = path3.join(root, "src", "tailwind.css");
6390
+ const cssPath = path6__default.join(root, "src", "tailwind.css");
6323
6391
  if (await pathExists2(cssPath)) return 0;
6324
6392
  await writeFileSafe(cssPath, DEFAULT_TAILWIND_CSS, { dryRun });
6325
6393
  return 1;
@@ -6332,7 +6400,7 @@ async function runMigrateCli(rawArgs) {
6332
6400
  verbose: process.env.TWS_VERBOSE === "1" || process.env.VERBOSE === "1"
6333
6401
  });
6334
6402
  const target = firstPositional(rawArgs) ?? ".";
6335
- const root = path3.resolve(process.cwd(), target);
6403
+ const root = path6__default.resolve(process.cwd(), target);
6336
6404
  const dryRunFlag = hasFlag("dry-run", rawArgs);
6337
6405
  const wizardOptions = hasFlag("wizard", rawArgs) ? await runMigrationWizard() : null;
6338
6406
  const { dryRun, includeConfig, includeClasses, includeImports } = wizardOptions ? {
@@ -6356,12 +6424,12 @@ async function runMigrateCli(rawArgs) {
6356
6424
  report.configWrites += await migrateConfig(root, dryRun);
6357
6425
  }
6358
6426
  for (const filePath of files) {
6359
- const source = await fs4.readFile(filePath, "utf8");
6427
+ const source = await fs7.readFile(filePath, "utf8");
6360
6428
  const migrated = migrateSource(source, { includeImports, includeClasses });
6361
6429
  if (migrated.output !== source) {
6362
6430
  report.updatedFiles++;
6363
6431
  if (!dryRun) {
6364
- await fs4.writeFile(filePath, migrated.output, "utf8");
6432
+ await fs7.writeFile(filePath, migrated.output, "utf8");
6365
6433
  }
6366
6434
  }
6367
6435
  report.classRenames += migrated.classRenames;
@@ -6425,10 +6493,10 @@ function buildClassNames(files, uniqueClasses) {
6425
6493
  });
6426
6494
  }
6427
6495
  function writeScanCache(root, cacheData) {
6428
- const cacheDir = path3.join(root, ".tailwind-styled");
6429
- const cachePath = path3.join(cacheDir, "scan-cache.json");
6430
- fs8.mkdirSync(cacheDir, { recursive: true });
6431
- fs8.writeFileSync(cachePath, JSON.stringify(cacheData, null, 2), "utf-8");
6496
+ const cacheDir = path6__default.join(root, ".tailwind-styled");
6497
+ const cachePath = path6__default.join(cacheDir, "scan-cache.json");
6498
+ fs11__default.mkdirSync(cacheDir, { recursive: true });
6499
+ fs11__default.writeFileSync(cachePath, JSON.stringify(cacheData, null, 2), "utf-8");
6432
6500
  return cachePath;
6433
6501
  }
6434
6502
  async function runScanCli(rawArgs) {
@@ -6440,7 +6508,7 @@ async function runScanCli(rawArgs) {
6440
6508
  debug: process.env.TWS_DEBUG === "1" || process.env.DEBUG === "1",
6441
6509
  verbose: process.env.TWS_VERBOSE === "1" || process.env.VERBOSE === "1"
6442
6510
  });
6443
- const root = path3.resolve(process.cwd(), target);
6511
+ const root = path6__default.resolve(process.cwd(), target);
6444
6512
  const spinner = output.spinner();
6445
6513
  spinner.start(`Scanning ${root}`);
6446
6514
  const scanned = await scanWorkspaceAsync(root);
@@ -6730,7 +6798,7 @@ var writeVerboseLine = (binary, args) => {
6730
6798
  console.error(` [verbose] $ ${formatCommand(binary, args)}`);
6731
6799
  };
6732
6800
  var runCommand = async (binary, args, options = {}) => {
6733
- return new Promise((resolve, reject) => {
6801
+ return new Promise((resolve2, reject) => {
6734
6802
  if (isVerboseEnabled(options)) {
6735
6803
  writeVerboseLine(binary, args);
6736
6804
  }
@@ -6757,7 +6825,7 @@ var runCommand = async (binary, args, options = {}) => {
6757
6825
  );
6758
6826
  return;
6759
6827
  }
6760
- resolve(exitCode);
6828
+ resolve2(exitCode);
6761
6829
  });
6762
6830
  });
6763
6831
  };
@@ -6786,7 +6854,7 @@ var formatCommandFailureOutput = (stdout, stderr) => {
6786
6854
  return "Command failed with no output.";
6787
6855
  };
6788
6856
  var runCommandCapture = async (binary, args, options = {}) => {
6789
- return new Promise((resolve, reject) => {
6857
+ return new Promise((resolve2, reject) => {
6790
6858
  if (isVerboseEnabled(options)) {
6791
6859
  writeVerboseLine(binary, args);
6792
6860
  }
@@ -6829,7 +6897,7 @@ ${formatCommandFailureOutput(stdout, stderr)}`,
6829
6897
  );
6830
6898
  return;
6831
6899
  }
6832
- resolve({
6900
+ resolve2({
6833
6901
  exitCode,
6834
6902
  stdout,
6835
6903
  stderr
@@ -6867,12 +6935,12 @@ function configureSetupFlags(rawArgs) {
6867
6935
  };
6868
6936
  }
6869
6937
  async function readPackageJson(cwd2) {
6870
- return readJsonSafe(path3.join(cwd2, "package.json"));
6938
+ return readJsonSafe(path6__default.join(cwd2, "package.json"));
6871
6939
  }
6872
6940
  async function detectPm(cwd2) {
6873
- if (await pathExists2(path3.join(cwd2, "bun.lockb"))) return "bun";
6874
- if (await pathExists2(path3.join(cwd2, "pnpm-lock.yaml"))) return "pnpm";
6875
- if (await pathExists2(path3.join(cwd2, "yarn.lock"))) return "yarn";
6941
+ if (await pathExists2(path6__default.join(cwd2, "bun.lockb"))) return "bun";
6942
+ if (await pathExists2(path6__default.join(cwd2, "pnpm-lock.yaml"))) return "pnpm";
6943
+ if (await pathExists2(path6__default.join(cwd2, "yarn.lock"))) return "yarn";
6876
6944
  return "npm";
6877
6945
  }
6878
6946
  async function detectBundler(cwd2) {
@@ -6893,7 +6961,7 @@ async function alreadyInstalled(cwd2, pkgName) {
6893
6961
  }
6894
6962
  async function findExisting(cwd2, names) {
6895
6963
  for (const name of names) {
6896
- const resolved = path3.join(cwd2, name);
6964
+ const resolved = path6__default.join(cwd2, name);
6897
6965
  if (await pathExists2(resolved)) return resolved;
6898
6966
  }
6899
6967
  return null;
@@ -7033,16 +7101,10 @@ var runSetupCli = async (rawArgs) => {
7033
7101
  output.writeText(import_picocolors3.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
7034
7102
  output.writeText("");
7035
7103
  output.writeText(import_picocolors3.default.bold(" [1/4]") + import_picocolors3.default.cyan(" packages"));
7036
- const [hasCorePkg, hasMergePkg] = await Promise.all([
7037
- alreadyInstalled(cwd, "tailwind-styled-v4"),
7038
- alreadyInstalled(cwd, "tailwind-merge")
7039
- ]);
7040
- const toInstall = [
7041
- hasCorePkg ? null : "tailwind-styled-v4",
7042
- hasMergePkg ? null : "tailwind-merge"
7043
- ].filter(Boolean);
7104
+ const hasCorePkg = await alreadyInstalled(cwd, "tailwind-styled-v4");
7105
+ const toInstall = hasCorePkg ? [] : ["tailwind-styled-v4"];
7044
7106
  if (toInstall.length > 0) await installPackages(cwd, pm, toInstall, false, setupFlags, logger);
7045
- else logger.skip("tailwind-styled-v4 + tailwind-merge sudah terpasang");
7107
+ else logger.skip("tailwind-styled-v4 sudah terpasang");
7046
7108
  output.writeText("\n" + import_picocolors3.default.bold(" [2/4]") + import_picocolors3.default.cyan(" bundler config"));
7047
7109
  const bundlerConfigMap = {
7048
7110
  next: {
@@ -7065,7 +7127,7 @@ var runSetupCli = async (rawArgs) => {
7065
7127
  if (bundlerConfig) {
7066
7128
  const cfg = await findExisting(cwd, bundlerConfig.files);
7067
7129
  if (cfg)
7068
- await patchFileWithDryRun(cfg, bundlerConfig.patcher, path3.basename(cfg), setupFlags, logger);
7130
+ await patchFileWithDryRun(cfg, bundlerConfig.patcher, path6__default.basename(cfg), setupFlags, logger);
7069
7131
  else logger.warn(bundlerConfig.warnMsg);
7070
7132
  } else {
7071
7133
  logger.skip("React tanpa bundler - tidak ada bundler config yang di-patch");
@@ -7084,8 +7146,8 @@ var runSetupCli = async (rawArgs) => {
7084
7146
  if (cssFile) {
7085
7147
  await patchFileWithDryRun(
7086
7148
  cssFile,
7087
- (src) => patchTailwindCss(src, bundler, path3.relative(cwd, cssFile), cwd),
7088
- path3.relative(cwd, cssFile),
7149
+ (src) => patchTailwindCss(src, bundler, path6__default.relative(cwd, cssFile), cwd),
7150
+ path6__default.relative(cwd, cssFile),
7089
7151
  setupFlags,
7090
7152
  logger
7091
7153
  );
@@ -7093,7 +7155,7 @@ var runSetupCli = async (rawArgs) => {
7093
7155
  logger.warn('CSS entry tidak ditemukan \u2014 tambahkan @import "tailwindcss" manual ke globals.css');
7094
7156
  }
7095
7157
  output.writeText("\n" + import_picocolors3.default.bold(" [4/4]") + import_picocolors3.default.cyan(" tsconfig.json"));
7096
- const tsCfg = path3.join(cwd, "tsconfig.json");
7158
+ const tsCfg = path6__default.join(cwd, "tsconfig.json");
7097
7159
  const hasTsConfig = await findExisting(cwd, ["tsconfig.json"]);
7098
7160
  if (hasTsConfig) {
7099
7161
  await patchFileWithDryRun(tsCfg, patchTsConfig, "tsconfig.json", setupFlags, logger);
@@ -7159,7 +7221,7 @@ async function runStatsCli(args) {
7159
7221
  verbose: process.env.TWS_VERBOSE === "1" || process.env.VERBOSE === "1"
7160
7222
  });
7161
7223
  const dirArg = parsed.positionals[0] ?? ".";
7162
- const dir = path3.resolve(process.cwd(), dirArg);
7224
+ const dir = path6__default.resolve(process.cwd(), dirArg);
7163
7225
  if (!await pathExists2(dir)) {
7164
7226
  throw new CliUsageError(`Directory not found: ${dir}`);
7165
7227
  }
@@ -7371,7 +7433,7 @@ function enumerateVariantProps(matrix) {
7371
7433
  }
7372
7434
  async function resolveScript(context, relativeToRepoRoot) {
7373
7435
  const fromRuntime = await resolveMonorepoPath(context.runtimeDir, relativeToRepoRoot);
7374
- const fromCwd = path3.resolve(process.cwd(), relativeToRepoRoot);
7436
+ const fromCwd = path6__default.resolve(process.cwd(), relativeToRepoRoot);
7375
7437
  const resolved = await firstExistingPath([fromRuntime, fromCwd]);
7376
7438
  if (!resolved) {
7377
7439
  throw new CliUsageError(`Required script not found: ${relativeToRepoRoot}`);
@@ -7385,13 +7447,13 @@ async function loadRegistry(context) {
7385
7447
  );
7386
7448
  const candidates = [
7387
7449
  runtimeRegistryPath,
7388
- path3.resolve(process.cwd(), "packages/domain/plugin-registry/registry.json")
7450
+ path6__default.resolve(process.cwd(), "packages/domain/plugin-registry/registry.json")
7389
7451
  ];
7390
7452
  const registryPath = await firstExistingPath(candidates);
7391
7453
  if (!registryPath) {
7392
7454
  throw new CliUsageError("Plugin registry file not found.");
7393
7455
  }
7394
- const raw = await fs4.readFile(registryPath, "utf8");
7456
+ const raw = await fs7.readFile(registryPath, "utf8");
7395
7457
  const data = JSON.parse(raw);
7396
7458
  return [
7397
7459
  ...data.official.map((item) => ({ ...item, official: true })),
@@ -7441,7 +7503,7 @@ init_json();
7441
7503
  var postJson = async (url, body, token) => {
7442
7504
  const { default: https } = await import('https');
7443
7505
  const { default: http } = await import('http');
7444
- return new Promise((resolve, reject) => {
7506
+ return new Promise((resolve2, reject) => {
7445
7507
  const client = url.protocol === "https:" ? https : http;
7446
7508
  const req = client.request(
7447
7509
  url,
@@ -7459,9 +7521,9 @@ var postJson = async (url, body, token) => {
7459
7521
  res.on("end", () => {
7460
7522
  const raw = Buffer.concat(chunks).toString("utf8");
7461
7523
  try {
7462
- resolve({ status: res.statusCode, body: JSON.parse(raw) });
7524
+ resolve2({ status: res.statusCode, body: JSON.parse(raw) });
7463
7525
  } catch {
7464
- resolve({ status: res.statusCode, body: raw });
7526
+ resolve2({ status: res.statusCode, body: raw });
7465
7527
  }
7466
7528
  });
7467
7529
  }
@@ -7490,7 +7552,7 @@ var deployCommand = {
7490
7552
  const version = typeof parsed.values.version === "string" ? parsed.values.version : "0.1.0";
7491
7553
  const tag = typeof parsed.values.tag === "string" ? parsed.values.tag : "latest";
7492
7554
  const registryUrl = typeof parsed.values.registry === "string" ? parsed.values.registry : process.env.TW_REGISTRY_URL ?? null;
7493
- const pkgPath = path3.join(process.cwd(), "package.json");
7555
+ const pkgPath = path6__default.join(process.cwd(), "package.json");
7494
7556
  if (!await pathExists2(pkgPath)) {
7495
7557
  throw new CliUsageError("[tw deploy] No package.json found in current directory");
7496
7558
  }
@@ -7525,10 +7587,10 @@ var deployCommand = {
7525
7587
  }
7526
7588
  return;
7527
7589
  }
7528
- const cacheDir = path3.join(process.cwd(), ".tw-cache");
7529
- await fs4.mkdir(cacheDir, { recursive: true });
7530
- await fs4.writeFile(
7531
- path3.join(cacheDir, "deploy-manifest.json"),
7590
+ const cacheDir = path6__default.join(process.cwd(), ".tw-cache");
7591
+ await fs7.mkdir(cacheDir, { recursive: true });
7592
+ await fs7.writeFile(
7593
+ path6__default.join(cacheDir, "deploy-manifest.json"),
7532
7594
  JSON.stringify(manifest, null, 2)
7533
7595
  );
7534
7596
  if (!registryUrl) {
@@ -7628,24 +7690,24 @@ function addIssue(issues, severity, type, message, suggestion, location) {
7628
7690
  issues.push({ severity, type, message, suggestion, location });
7629
7691
  }
7630
7692
  function readJsonFile(filePath) {
7631
- if (!fs8.existsSync(filePath)) return null;
7693
+ if (!fs11__default.existsSync(filePath)) return null;
7632
7694
  try {
7633
- return JSON.parse(fs8.readFileSync(filePath, "utf8"));
7695
+ return JSON.parse(fs11__default.readFileSync(filePath, "utf8"));
7634
7696
  } catch {
7635
7697
  return null;
7636
7698
  }
7637
7699
  }
7638
7700
  function findWorkspacePackageJsonFiles(root) {
7639
- const packagesDir = path3.join(root, "packages");
7640
- if (!fs8.existsSync(packagesDir)) return [];
7641
- return fs8.readdirSync(packagesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path3.join(packagesDir, entry.name, "package.json")).filter((filePath) => fs8.existsSync(filePath));
7701
+ const packagesDir = path6__default.join(root, "packages");
7702
+ if (!fs11__default.existsSync(packagesDir)) return [];
7703
+ return fs11__default.readdirSync(packagesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path6__default.join(packagesDir, entry.name, "package.json")).filter((filePath) => fs11__default.existsSync(filePath));
7642
7704
  }
7643
7705
  function findFiles(dir, ext) {
7644
7706
  const files = [];
7645
7707
  try {
7646
- const entries = fs8.readdirSync(dir, { withFileTypes: true });
7708
+ const entries = fs11__default.readdirSync(dir, { withFileTypes: true });
7647
7709
  for (const entry of entries) {
7648
- const fullPath = path3.join(dir, entry.name);
7710
+ const fullPath = path6__default.join(dir, entry.name);
7649
7711
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
7650
7712
  files.push(...findFiles(fullPath, ext));
7651
7713
  } else if (entry.isFile() && entry.name.endsWith(ext)) {
@@ -7658,7 +7720,7 @@ function findFiles(dir, ext) {
7658
7720
  return files;
7659
7721
  }
7660
7722
  function runWorkspaceDiagnostics(root, issues, checks) {
7661
- const rootPackageJsonPath = path3.join(root, "package.json");
7723
+ const rootPackageJsonPath = path6__default.join(root, "package.json");
7662
7724
  const rootPackageJson = readJsonFile(rootPackageJsonPath);
7663
7725
  if (!rootPackageJson) {
7664
7726
  addCheck(
@@ -7711,7 +7773,7 @@ function runWorkspaceDiagnostics(root, issues, checks) {
7711
7773
  const scripts = typeof manifest.scripts === "object" && manifest.scripts !== null ? manifest.scripts : {};
7712
7774
  const missing = requiredScripts.filter((name) => typeof scripts[name] !== "string");
7713
7775
  if (missing.length === 0) return [];
7714
- const packageName = typeof manifest.name === "string" && manifest.name.length > 0 ? manifest.name : path3.basename(path3.dirname(filePath));
7776
+ const packageName = typeof manifest.name === "string" && manifest.name.length > 0 ? manifest.name : path6__default.basename(path6__default.dirname(filePath));
7715
7777
  return [{ packageName, missing }];
7716
7778
  });
7717
7779
  if (missingScripts.length === 0) {
@@ -7746,7 +7808,7 @@ function runWorkspaceDiagnostics(root, issues, checks) {
7746
7808
  );
7747
7809
  }
7748
7810
  function runTailwindProjectDiagnostics(root, issues, checks) {
7749
- const packageJsonPath = path3.join(root, "package.json");
7811
+ const packageJsonPath = path6__default.join(root, "package.json");
7750
7812
  const packageJson = readJsonFile(packageJsonPath);
7751
7813
  if (!packageJson) {
7752
7814
  addCheck(
@@ -7805,7 +7867,7 @@ function runTailwindProjectDiagnostics(root, issues, checks) {
7805
7867
  const cssFiles = findFiles(root, ".css");
7806
7868
  const hasTailwindImport = cssFiles.slice(0, 10).some((filePath) => {
7807
7869
  try {
7808
- const content = fs8.readFileSync(filePath, "utf8");
7870
+ const content = fs11__default.readFileSync(filePath, "utf8");
7809
7871
  return content.includes("@tailwind") || content.includes('@import "tailwindcss"');
7810
7872
  } catch {
7811
7873
  return false;
@@ -7829,7 +7891,7 @@ function runTailwindProjectDiagnostics(root, issues, checks) {
7829
7891
  );
7830
7892
  }
7831
7893
  const configFiles = ["tailwind.config.js", "tailwind.config.ts", "tailwind.config.mjs"];
7832
- const hasConfig = configFiles.some((name) => fs8.existsSync(path3.join(root, name)));
7894
+ const hasConfig = configFiles.some((name) => fs11__default.existsSync(path6__default.join(root, name)));
7833
7895
  addCheck(
7834
7896
  checks,
7835
7897
  "tailwind",
@@ -7838,7 +7900,7 @@ function runTailwindProjectDiagnostics(root, issues, checks) {
7838
7900
  "info",
7839
7901
  hasConfig ? "Tailwind config file detected." : "No tailwind.config file found."
7840
7902
  );
7841
- const tsconfig = readJsonFile(path3.join(root, "tsconfig.json"));
7903
+ const tsconfig = readJsonFile(path6__default.join(root, "tsconfig.json"));
7842
7904
  const jsx = tsconfig?.compilerOptions?.jsx;
7843
7905
  addCheck(
7844
7906
  checks,
@@ -8004,7 +8066,7 @@ async function runAnalysisDiagnostics(root, issues, checks, verbose) {
8004
8066
  }
8005
8067
  }
8006
8068
  var runDiagnostics = async (options = {}) => {
8007
- const root = path3.resolve(options.root ?? process.cwd());
8069
+ const root = path6__default.resolve(options.root ?? process.cwd());
8008
8070
  const includes = parseIncludes(options.include);
8009
8071
  const issues = [];
8010
8072
  const checks = [];
@@ -8154,7 +8216,7 @@ var shareCommand = {
8154
8216
  name: "share",
8155
8217
  async run(args, context) {
8156
8218
  const name = args.find((arg) => !arg.startsWith("-")) ?? "component-name";
8157
- const manifestPath = path3.join(process.cwd(), ".tw-cache", "deploy-manifest.json");
8219
+ const manifestPath = path6__default.join(process.cwd(), ".tw-cache", "deploy-manifest.json");
8158
8220
  const defaultManifest = {
8159
8221
  name,
8160
8222
  version: "0.1.0"
@@ -8240,14 +8302,14 @@ var isVersionOutdated = (currentVersion, latestVersion) => {
8240
8302
  };
8241
8303
  var resolveCurrentCliVersion = async (context) => {
8242
8304
  const candidates = [
8243
- path3.resolve(context.runtimeDir, "..", "package.json"),
8244
- path3.resolve(process.cwd(), "packages", "cli", "package.json"),
8245
- path3.resolve(process.cwd(), "package.json")
8305
+ path6__default.resolve(context.runtimeDir, "..", "package.json"),
8306
+ path6__default.resolve(process.cwd(), "packages", "cli", "package.json"),
8307
+ path6__default.resolve(process.cwd(), "package.json")
8246
8308
  ];
8247
8309
  for (const candidate of candidates) {
8248
8310
  if (!await pathExists2(candidate)) continue;
8249
8311
  const pkg = await readJsonSafe(candidate);
8250
- const isCliPackage = pkg?.version && (pkg.name === CLI_PACKAGE_NAME || candidate.includes(`${path3.sep}packages${path3.sep}cli${path3.sep}`));
8312
+ const isCliPackage = pkg?.version && (pkg.name === CLI_PACKAGE_NAME || candidate.includes(`${path6__default.sep}packages${path6__default.sep}cli${path6__default.sep}`));
8251
8313
  if (isCliPackage) return pkg.version ?? "0.0.0";
8252
8314
  }
8253
8315
  return "0.0.0";
@@ -8520,7 +8582,7 @@ function resolveCliEntry(scriptPath) {
8520
8582
  async function hasTailwindCssImport(cwd2) {
8521
8583
  const cssFiles = ["src/app/globals.css", "src/index.css", "src/style.css", "app/globals.css"];
8522
8584
  for (const file of cssFiles) {
8523
- const raw = await readFileSafe(path3.join(cwd2, file));
8585
+ const raw = await readFileSafe(path6__default.join(cwd2, file));
8524
8586
  if (raw?.includes("tailwindcss")) return true;
8525
8587
  }
8526
8588
  return false;
@@ -8536,7 +8598,7 @@ async function hasSafelistSource(cwd2) {
8536
8598
  "app/globals.css"
8537
8599
  ];
8538
8600
  for (const file of cssFiles) {
8539
- const raw = await readFileSafe(path3.join(cwd2, file));
8601
+ const raw = await readFileSafe(path6__default.join(cwd2, file));
8540
8602
  if (raw === null) continue;
8541
8603
  if (raw.includes("tw-classes")) return { found: true, cssFile: file };
8542
8604
  if (raw.includes("tailwindcss")) return { found: false, cssFile: file };
@@ -8544,8 +8606,8 @@ async function hasSafelistSource(cwd2) {
8544
8606
  return { found: false, cssFile: null };
8545
8607
  }
8546
8608
  async function applyTailwindInit(cwd2) {
8547
- await ensureFileSafe(path3.join(cwd2, "src", "tailwind.css"), DEFAULT_TAILWIND_CSS2);
8548
- await ensureFileSafe(path3.join(cwd2, "tailwind-styled.config.json"), DEFAULT_TW_CONFIG);
8609
+ await ensureFileSafe(path6__default.join(cwd2, "src", "tailwind.css"), DEFAULT_TAILWIND_CSS2);
8610
+ await ensureFileSafe(path6__default.join(cwd2, "tailwind-styled.config.json"), DEFAULT_TW_CONFIG);
8549
8611
  }
8550
8612
  function check(results, id, label, pass, message, fix) {
8551
8613
  results.push({ id, label, pass, message, fix });
@@ -8567,7 +8629,7 @@ async function runPreflightCli(rawArgs) {
8567
8629
  node.major >= 20 ? `Node ${node.full} OK` : `Node ${node.full} - requires >=20. Download: https://nodejs.org`,
8568
8630
  node.major < 20 ? "Install Node.js 20 LTS or newer from https://nodejs.org" : void 0
8569
8631
  );
8570
- const pkg = await readJsonSafe(path3.join(cwd2, "package.json"));
8632
+ const pkg = await readJsonSafe(path6__default.join(cwd2, "package.json"));
8571
8633
  check(
8572
8634
  results,
8573
8635
  "package-json",
@@ -8598,19 +8660,10 @@ async function runPreflightCli(rawArgs) {
8598
8660
  hasBundler ? `${bundlerName} detected OK` : "No supported bundler (Vite/Next.js/Rspack) found",
8599
8661
  "Install a bundler: npm install vite @vitejs/plugin-react OR npx create-next-app"
8600
8662
  );
8601
- const hasMerge = pkgHasDep(pkg, "tailwind-merge");
8602
- check(
8603
- results,
8604
- "tailwind-merge",
8605
- "tailwind-merge installed",
8606
- hasMerge,
8607
- hasMerge ? "tailwind-merge found OK" : "Missing peer dep - run: npm install tailwind-merge",
8608
- "npm install tailwind-merge"
8609
- );
8610
8663
  }
8611
8664
  const twConfigFiles = ["tailwind.config.ts", "tailwind.config.js", "tailwind.config.mjs"];
8612
8665
  const twConfigChecks = await Promise.all(
8613
- twConfigFiles.map(async (file) => ({ file, exists: await pathExists2(path3.join(cwd2, file)) }))
8666
+ twConfigFiles.map(async (file) => ({ file, exists: await pathExists2(path6__default.join(cwd2, file)) }))
8614
8667
  );
8615
8668
  const foundTwConfig = twConfigChecks.find((item) => item.exists)?.file ?? null;
8616
8669
  const hasCssConfig = await hasTailwindCssImport(cwd2);
@@ -8622,7 +8675,7 @@ async function runPreflightCli(rawArgs) {
8622
8675
  foundTwConfig ? `${foundTwConfig} found OK` : hasCssConfig ? "@import tailwindcss found in CSS OK" : "No Tailwind config found - run: tw init",
8623
8676
  "tw init"
8624
8677
  );
8625
- const oldConfig = await readJsonSafe(path3.join(cwd2, "tailwind.config.js")) ?? await readJsonSafe(path3.join(cwd2, "tailwind.config.ts"));
8678
+ const oldConfig = await readJsonSafe(path6__default.join(cwd2, "tailwind.config.js")) ?? await readJsonSafe(path6__default.join(cwd2, "tailwind.config.ts"));
8626
8679
  if (oldConfig) {
8627
8680
  const hasOldJit = oldConfig.mode === "jit";
8628
8681
  const hasOldPurge = "purge" in oldConfig;
@@ -8636,7 +8689,7 @@ async function runPreflightCli(rawArgs) {
8636
8689
  "Run: tw migrate --dry-run to see migration steps"
8637
8690
  );
8638
8691
  }
8639
- const hasTsConfig = await pathExists2(path3.join(cwd2, "tsconfig.json"));
8692
+ const hasTsConfig = await pathExists2(path6__default.join(cwd2, "tsconfig.json"));
8640
8693
  check(
8641
8694
  results,
8642
8695
  "typescript",
@@ -9030,7 +9083,7 @@ var storybookCommand = {
9030
9083
  context.output.writeText(
9031
9084
  `[tw storybook] Tip: use --variants='{"size":["sm","lg"]}' to enumerate variant combinations`
9032
9085
  );
9033
- const localBin = path3.join(
9086
+ const localBin = path6__default.join(
9034
9087
  process.cwd(),
9035
9088
  "node_modules",
9036
9089
  ".bin",
@@ -9227,418 +9280,269 @@ function getNativeEngineBinding() {
9227
9280
  // packages/domain/engine/src/bundleAnalyzer.ts
9228
9281
  var BundleAnalyzer = class {
9229
9282
  analyzeClass(className, scanResult, css) {
9230
- if (!className || className.trim() === "") {
9231
- throw new Error("Class name cannot be empty");
9232
- }
9233
- if (!scanResult) {
9234
- throw new Error("Scan result is required for analysis");
9283
+ if (!className || className.trim() === "") throw new Error("Class name cannot be empty");
9284
+ if (!scanResult) throw new Error("Scan result is required for analysis");
9285
+ if (typeof css !== "string") throw new Error("CSS string is required for analysis");
9286
+ const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9287
+ const native = getNativeEngineBinding();
9288
+ if (!native.analyzeClassUsage) {
9289
+ throw new Error("FATAL: Native binding 'analyzeClassUsage' is required but not available.");
9235
9290
  }
9236
- if (typeof css !== "string") {
9237
- throw new Error("CSS string is required for analysis");
9291
+ if (!native.buildDependencyChain) {
9292
+ throw new Error("FATAL: Native binding 'buildDependencyChain' is required but not available.");
9238
9293
  }
9239
- const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9240
- const usageCount = this.countClassUsage(normalizedClass, scanResult);
9241
- const files = this.getFilesUsingClass(normalizedClass, scanResult);
9242
- const bundleSize = this.calculateBundleContribution(normalizedClass, css);
9243
- const variantChains = this.extractVariantChains(normalizedClass, css);
9244
- const dependencies = this.extractDependencies(normalizedClass, css);
9245
- const isDeadCode = this.checkIsDeadCode(normalizedClass, scanResult, css);
9294
+ const results = native.analyzeClassUsage(
9295
+ [normalizedClass],
9296
+ JSON.stringify(scanResult),
9297
+ css
9298
+ );
9299
+ const info = results[0];
9300
+ const files = info ? JSON.parse(info.filesJson).map((f) => ({ file: f, line: 1, column: 1 })) : [];
9301
+ const dependencies = native.buildDependencyChain(normalizedClass);
9246
9302
  return {
9247
9303
  className: normalizedClass,
9248
- totalUsage: usageCount,
9304
+ totalUsage: info?.usageCount ?? 0,
9249
9305
  files,
9250
- bundleSizeBytes: bundleSize,
9251
- variantChains,
9252
- isDeadCode,
9306
+ bundleSizeBytes: info?.bundleSizeBytes ?? 0,
9307
+ variantChains: [],
9308
+ isDeadCode: info?.isDeadCode ?? true,
9253
9309
  dependencies
9254
9310
  };
9255
9311
  }
9256
9312
  analyzeAll(scanResult, css) {
9257
- if (!scanResult) {
9258
- throw new Error("Scan result is required for analysis");
9259
- }
9260
- if (typeof css !== "string") {
9261
- throw new Error("CSS string is required for analysis");
9262
- }
9263
- const results = /* @__PURE__ */ new Map();
9264
- const allClasses = new Set(scanResult.uniqueClasses);
9265
- const cssClasses = this.extractClassesFromCss(css);
9266
- for (const cssClass of cssClasses) {
9267
- allClasses.add(cssClass);
9268
- }
9269
- for (const className of allClasses) {
9270
- try {
9271
- const result = this.analyzeClass(className, scanResult, css);
9272
- results.set(className, result);
9273
- } catch (error) {
9274
- console.warn(`Failed to analyze class "${className}":`, error);
9275
- }
9313
+ if (!scanResult) throw new Error("Scan result is required for analysis");
9314
+ if (typeof css !== "string") throw new Error("CSS string is required for analysis");
9315
+ const native = getNativeEngineBinding();
9316
+ if (!native.analyzeClassUsage) {
9317
+ throw new Error("FATAL: Native binding 'analyzeClassUsage' is required but not available.");
9318
+ }
9319
+ if (!native.buildDependencyChain) {
9320
+ throw new Error("FATAL: Native binding 'buildDependencyChain' is required but not available.");
9321
+ }
9322
+ const allClasses = Array.from(/* @__PURE__ */ new Set([
9323
+ ...scanResult.uniqueClasses,
9324
+ ...native.extractAllClasses ? native.extractAllClasses(css) : []
9325
+ ]));
9326
+ const results = native.analyzeClassUsage(
9327
+ allClasses,
9328
+ JSON.stringify(scanResult),
9329
+ css
9330
+ );
9331
+ const map = /* @__PURE__ */ new Map();
9332
+ for (const info of results) {
9333
+ const files = JSON.parse(info.filesJson).map((f) => ({
9334
+ file: f,
9335
+ line: 1,
9336
+ column: 1
9337
+ }));
9338
+ const dependencies = native.buildDependencyChain ? native.buildDependencyChain(info.className) : [];
9339
+ map.set(info.className, {
9340
+ className: info.className,
9341
+ totalUsage: info.usageCount,
9342
+ files,
9343
+ bundleSizeBytes: info.bundleSizeBytes,
9344
+ variantChains: [],
9345
+ isDeadCode: info.isDeadCode,
9346
+ dependencies
9347
+ });
9276
9348
  }
9277
- return results;
9349
+ return map;
9278
9350
  }
9279
9351
  calculateBundleContribution(className, css) {
9280
9352
  if (!className || className.trim() === "") throw new Error("Class name cannot be empty");
9281
9353
  if (typeof css !== "string") throw new Error("CSS string is required");
9282
- try {
9283
- const native = (() => {
9284
- try {
9285
- return getNativeEngineBinding();
9286
- } catch {
9287
- return null;
9288
- }
9289
- })();
9290
- if (native?.calculateBundleContributionsNative) {
9291
- const r = native.calculateBundleContributionsNative([className], css);
9292
- return r?.[0]?.sizeBytes ?? 0;
9293
- }
9294
- } catch (err) {
9354
+ const native = getNativeEngineBinding();
9355
+ if (!native.calculateBundleContributions) {
9356
+ throw new Error("FATAL: Native binding 'calculateBundleContributions' is required but not available.");
9295
9357
  }
9296
- const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9297
- const escapedClass = normalizedClass.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9298
- const selectorPattern = new RegExp(`\\.${escapedClass}([\\s:{]|$)`, "g");
9299
- if (!css.match(selectorPattern)) return 0;
9300
- const classSelector = `.${normalizedClass}`;
9301
- return css.split("\n").filter((l) => l.includes(classSelector)).reduce((sum, l) => {
9302
- const s = l.indexOf("{");
9303
- return s !== -1 ? sum + l.substring(s).length + 1 : sum;
9304
- }, 0);
9358
+ const r = native.calculateBundleContributions([className], css);
9359
+ return r?.[0]?.sizeBytes ?? 0;
9305
9360
  }
9306
9361
  detectDeadCode(scanResult, css) {
9307
9362
  if (!scanResult) throw new Error("Scan result is required for dead code detection");
9308
9363
  if (typeof css !== "string") throw new Error("CSS string is required for dead code detection");
9309
- try {
9310
- const native = (() => {
9311
- try {
9312
- return getNativeEngineBinding();
9313
- } catch {
9314
- return null;
9315
- }
9316
- })();
9317
- if (native?.detectDeadCodeNative) {
9318
- const r = native.detectDeadCodeNative(JSON.stringify(scanResult), css);
9319
- return r?.deadInCss ?? [];
9320
- }
9321
- } catch (err) {
9322
- }
9323
- const cssClasses = this.extractClassesFromCss(css);
9324
- const usedClasses = new Set(scanResult.uniqueClasses);
9325
- return cssClasses.filter((c) => !usedClasses.has(c));
9326
- }
9327
- countClassUsage(className, scanResult) {
9328
- const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9329
- const count = scanResult.files.reduce((sum, file) => {
9330
- return sum + file.classes.filter((fileClass) => {
9331
- const normalizedFileClass = fileClass.startsWith(".") ? fileClass.slice(1) : fileClass;
9332
- return normalizedFileClass === normalizedClass;
9333
- }).length;
9334
- }, 0);
9335
- return count;
9336
- }
9337
- getFilesUsingClass(className, scanResult) {
9338
- const files = [];
9339
- const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9340
- for (const file of scanResult.files) {
9341
- for (const fileClass of file.classes) {
9342
- const normalizedFileClass = fileClass.startsWith(".") ? fileClass.slice(1) : fileClass;
9343
- if (normalizedFileClass === normalizedClass) {
9344
- files.push({
9345
- file: file.file,
9346
- line: 1,
9347
- column: 1
9348
- });
9349
- break;
9350
- }
9351
- }
9352
- }
9353
- return files;
9354
- }
9355
- extractVariantChains(className, css) {
9356
- const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9357
- const variantChains = [];
9358
- const escapedClass = normalizedClass.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9359
- const variantPattern = new RegExp(`([\\w-]+:${escapedClass}|${escapedClass})`, "g");
9360
- const lines = css.split("\n");
9361
- for (const line of lines) {
9362
- const matches = line.match(variantPattern);
9363
- if (matches) {
9364
- for (const match of matches) {
9365
- if (match.includes(":")) {
9366
- variantChains.push(match);
9367
- }
9368
- }
9369
- }
9370
- }
9371
- return [...new Set(variantChains)];
9372
- }
9373
- extractDependencies(className, _css) {
9374
- const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9375
- const parts = normalizedClass.split(":");
9376
- const dependencies = parts.slice(0, -1).map((_, i) => parts.slice(0, i + 1).join(":"));
9377
- return dependencies;
9378
- }
9379
- checkIsDeadCode(className, scanResult, css) {
9380
- const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9381
- const cssClasses = this.extractClassesFromCss(css);
9382
- if (!cssClasses.includes(normalizedClass)) {
9383
- return true;
9384
- }
9385
- const usageCount = this.countClassUsage(normalizedClass, scanResult);
9386
- return usageCount === 0;
9387
- }
9388
- extractClassesFromCss(css) {
9389
- const classes = [];
9390
- const classPattern = /\.([a-zA-Z0-9_-]+(?::[a-zA-Z0-9_-]+)*)/g;
9391
- for (const match of css.matchAll(classPattern)) {
9392
- const className = match[1];
9393
- if (!classes.includes(className)) {
9394
- classes.push(className);
9395
- }
9364
+ const native = getNativeEngineBinding();
9365
+ if (!native.detectDeadCode) {
9366
+ throw new Error("FATAL: Native binding 'detectDeadCode' is required but not available.");
9396
9367
  }
9397
- return classes;
9368
+ const r = native.detectDeadCode(JSON.stringify(scanResult), css);
9369
+ return r?.deadInCss ?? [];
9398
9370
  }
9399
9371
  };
9400
9372
 
9401
9373
  // packages/domain/engine/src/impactTracker.ts
9402
9374
  var ImpactTracker = class {
9403
9375
  bundleAnalyzer;
9404
- criticalPatterns = [
9405
- "fixed",
9406
- "absolute",
9407
- "sticky",
9408
- "z-50",
9409
- "z-index",
9410
- "top-0",
9411
- "right-0",
9412
- "bottom-0",
9413
- "left-0",
9414
- "w-full",
9415
- "h-full",
9416
- "min-h-screen",
9417
- "flex",
9418
- "grid",
9419
- "block",
9420
- "inline",
9421
- "hidden",
9422
- "visible",
9423
- "opacity",
9424
- "pointer-events",
9425
- "cursor"
9426
- ];
9427
9376
  constructor() {
9428
9377
  this.bundleAnalyzer = new BundleAnalyzer();
9429
9378
  }
9430
- /**
9431
- * Analisis impact sebuah class menggunakan BundleAnalyzer untuk dapat
9432
- * data akurat tentang bundle size contribution.
9433
- *
9434
- * @param className - Tailwind class yang ingin dianalisis
9435
- * @param scanResult - Hasil scan workspace
9436
- * @param css - CSS string dari build output (opsional — jika tidak ada, gunakan estimasi)
9437
- */
9438
9379
  analyzeWithBundle(className, scanResult, css = "") {
9439
9380
  const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9440
- let bundleAnalysis = null;
9441
- try {
9442
- if (scanResult && css) {
9443
- bundleAnalysis = this.bundleAnalyzer.analyzeClass(normalizedClass, scanResult, css);
9444
- }
9445
- } catch {
9446
- }
9447
- const resolvedBundleAnalysis = bundleAnalysis ?? (() => {
9448
- const usedIn = (scanResult?.files ?? []).filter(
9449
- (f) => f.classes?.includes(normalizedClass)
9450
- );
9451
- return {
9452
- className: normalizedClass,
9453
- totalUsage: usedIn.length,
9454
- files: usedIn.map((f) => ({
9455
- file: f.file,
9456
- line: 1,
9457
- column: 1
9458
- })),
9459
- bundleSizeBytes: 0,
9460
- variantChains: [],
9461
- isDeadCode: usedIn.length === 0,
9462
- dependencies: []
9463
- };
9464
- })();
9465
- return this.calculateImpact(normalizedClass, resolvedBundleAnalysis, scanResult);
9381
+ const native = getNativeEngineBinding();
9382
+ if (!native?.calculateImpactScores) {
9383
+ throw new Error("FATAL: Native binding 'calculateImpactScores' is required but not available.");
9384
+ }
9385
+ const scores = native.calculateImpactScores(
9386
+ [normalizedClass],
9387
+ JSON.stringify(scanResult),
9388
+ css,
9389
+ 0.6,
9390
+ 0.4
9391
+ );
9392
+ const score = scores[0];
9393
+ const bundleAnalysis = {
9394
+ className: normalizedClass,
9395
+ totalUsage: score?.usageCount ?? 0,
9396
+ files: [],
9397
+ bundleSizeBytes: score?.sizeBytes ?? 0,
9398
+ variantChains: [],
9399
+ isDeadCode: (score?.usageCount ?? 0) === 0,
9400
+ dependencies: []
9401
+ };
9402
+ return this.calculateImpact(normalizedClass, bundleAnalysis, scanResult, score);
9466
9403
  }
9467
- /**
9468
- * Analisis semua class dalam workspace sekaligus.
9469
- */
9470
9404
  analyzeAll(scanResult, css = "") {
9471
- const results = /* @__PURE__ */ new Map();
9405
+ const native = getNativeEngineBinding();
9406
+ if (!native?.calculateImpactScores) {
9407
+ throw new Error("FATAL: Native binding 'calculateImpactScores' is required but not available.");
9408
+ }
9472
9409
  const classes = scanResult?.uniqueClasses ?? [];
9410
+ const scores = native.calculateImpactScores(
9411
+ classes,
9412
+ JSON.stringify(scanResult),
9413
+ css,
9414
+ 0.6,
9415
+ 0.4
9416
+ );
9417
+ const scoreMap = new Map(scores.map((s) => [s.className, s]));
9418
+ const results = /* @__PURE__ */ new Map();
9473
9419
  for (const cls of classes) {
9474
- try {
9475
- results.set(cls, this.analyzeWithBundle(cls, scanResult, css));
9476
- } catch {
9477
- }
9420
+ const score = scoreMap.get(cls);
9421
+ const bundleAnalysis = {
9422
+ className: cls,
9423
+ totalUsage: score?.usageCount ?? 0,
9424
+ files: [],
9425
+ bundleSizeBytes: score?.sizeBytes ?? 0,
9426
+ variantChains: [],
9427
+ isDeadCode: (score?.usageCount ?? 0) === 0,
9428
+ dependencies: []
9429
+ };
9430
+ results.set(cls, this.calculateImpact(cls, bundleAnalysis, scanResult, score));
9478
9431
  }
9479
9432
  return results;
9480
9433
  }
9481
- calculateImpact(className, bundleAnalysis, scanResult) {
9482
- if (!className || className.trim() === "") {
9483
- return this.createEmptyReport(className);
9484
- }
9485
- if (!bundleAnalysis) {
9486
- return this.createEmptyReport(className);
9487
- }
9434
+ calculateImpact(className, bundleAnalysis, scanResult, nativeScore) {
9435
+ if (!className || className.trim() === "") return this.createEmptyReport(className);
9436
+ if (!bundleAnalysis) return this.createEmptyReport(className);
9488
9437
  const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9489
- const affectedComponents = this.findAffectedComponents(normalizedClass, scanResult);
9490
- const directUsage = affectedComponents.filter((c) => c.usageType === "direct").length;
9491
- const indirectUsage = affectedComponents.filter((c) => c.usageType !== "direct").length;
9492
- const totalComponents = affectedComponents.length;
9438
+ const totalComponents = nativeScore?.usageCount ?? bundleAnalysis.totalUsage ?? 0;
9439
+ const directUsage = totalComponents;
9440
+ const indirectUsage = 0;
9493
9441
  const bundleSizeBytes = bundleAnalysis.bundleSizeBytes || 0;
9494
- const estimatedSavings = this.calculateSavings(bundleSizeBytes, totalComponents);
9495
- const impactReport = {
9496
- className: normalizedClass,
9497
- totalComponents,
9498
- directUsage,
9499
- indirectUsage,
9500
- bundleSizeBytes,
9501
- estimatedSavings,
9502
- riskLevel: "low",
9503
- suggestions: []
9504
- };
9505
- impactReport.riskLevel = this.calculateRisk(normalizedClass, impactReport);
9506
- impactReport.suggestions = this.generateSuggestions(normalizedClass, impactReport);
9507
- return impactReport;
9508
- }
9509
- findAffectedComponents(className, scanResult) {
9510
- const components = [];
9511
- if (!className || className.trim() === "") {
9512
- return components;
9513
- }
9514
- if (!scanResult || !Array.isArray(scanResult.files)) {
9515
- return components;
9516
- }
9517
- const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9518
- const classParts = normalizedClass.split(":");
9519
- for (const file of scanResult.files) {
9520
- if (!file || !file.file) continue;
9521
- const filePath = file.file;
9522
- const classes = file.classes || [];
9523
- const variants = file.variants || [];
9524
- for (const [i, fileClass] of classes.entries()) {
9525
- if (!fileClass) continue;
9526
- const normalizedFileClass = fileClass.startsWith(".") ? fileClass.slice(1) : fileClass;
9527
- if (normalizedFileClass === normalizedClass) {
9528
- components.push({
9529
- file: filePath,
9530
- line: file.lineNumbers?.[i] || 1,
9531
- column: file.columnNumbers?.[i] || 1,
9532
- usageType: "direct"
9533
- });
9534
- } else if (normalizedFileClass.includes(normalizedClass)) {
9535
- const variant = classParts.length > 1 ? classParts[0] : void 0;
9536
- components.push({
9537
- file: filePath,
9538
- line: file.lineNumbers?.[i] || 1,
9539
- column: file.columnNumbers?.[i] || 1,
9540
- usageType: "variant",
9541
- variant
9542
- });
9543
- }
9544
- }
9545
- for (const [i, variant] of variants.entries()) {
9546
- if (!variant) continue;
9547
- if (variant.includes(normalizedClass)) {
9548
- const baseClass = variant.split(":").pop();
9549
- if (baseClass === normalizedClass) {
9550
- components.push({
9551
- file: filePath,
9552
- line: file.lineNumbers?.[i] || 1,
9553
- column: file.columnNumbers?.[i] || 1,
9554
- usageType: "variant",
9555
- variant: variant.split(":")[0]
9556
- });
9557
- }
9558
- }
9559
- }
9560
- }
9561
- return components;
9562
- }
9563
- calculateRisk(className, impact) {
9564
- if (!className || className.trim() === "") {
9565
- return "low";
9566
- }
9567
- if (!impact) {
9568
- return "low";
9569
- }
9570
- const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9571
- if (impact.totalComponents > 10) {
9572
- return "high";
9573
- }
9574
- if (this.isCriticalClass(normalizedClass)) {
9575
- return "high";
9442
+ const native = getNativeEngineBinding();
9443
+ if (native?.computeImpactMetadata) {
9444
+ const impactJson = JSON.stringify({
9445
+ className: normalizedClass,
9446
+ totalComponents,
9447
+ indirectUsage,
9448
+ bundleSizeBytes
9449
+ });
9450
+ const result = JSON.parse(native.computeImpactMetadata(normalizedClass, impactJson));
9451
+ return {
9452
+ className: normalizedClass,
9453
+ totalComponents,
9454
+ directUsage,
9455
+ indirectUsage,
9456
+ bundleSizeBytes,
9457
+ estimatedSavings: result.estimatedSavings,
9458
+ riskLevel: result.riskLevel,
9459
+ suggestions: result.suggestions
9460
+ };
9576
9461
  }
9577
- if (impact.totalComponents >= 5 && impact.totalComponents <= 10) {
9578
- return "medium";
9462
+ if (native?.calculateImpact) {
9463
+ const impactJson = JSON.stringify({
9464
+ className: normalizedClass,
9465
+ totalComponents,
9466
+ indirectUsage,
9467
+ bundleSizeBytes
9468
+ });
9469
+ const result = JSON.parse(native.calculateImpact(impactJson));
9470
+ return {
9471
+ className: normalizedClass,
9472
+ totalComponents,
9473
+ directUsage,
9474
+ indirectUsage,
9475
+ bundleSizeBytes,
9476
+ estimatedSavings: result.estimatedSavings,
9477
+ riskLevel: result.riskLevel,
9478
+ suggestions: result.suggestions
9479
+ };
9579
9480
  }
9580
- return "low";
9481
+ throw new Error("FATAL: Native binding 'computeImpactMetadata' or 'calculateImpact' is required but not available.");
9581
9482
  }
9582
- generateSuggestions(className, impact) {
9583
- const suggestions = [];
9584
- if (!className || className.trim() === "") {
9585
- return suggestions;
9586
- }
9587
- if (!impact) {
9588
- return suggestions;
9483
+ findAffectedComponents(className, scanResult) {
9484
+ if (!className || !scanResult) return [];
9485
+ const native = getNativeEngineBinding();
9486
+ if (!native?.calculateImpactScores) {
9487
+ throw new Error("FATAL: Native binding 'calculateImpactScores' is required but not available.");
9589
9488
  }
9590
9489
  const normalizedClass = className.startsWith(".") ? className.slice(1) : className;
9591
- if (impact.riskLevel === "high") {
9592
- if (impact.totalComponents > 10) {
9593
- suggestions.push(
9594
- `This class is used in ${impact.totalComponents} components. Consider creating a utility component instead.`
9595
- );
9596
- }
9597
- if (this.isCriticalClass(normalizedClass)) {
9598
- suggestions.push(
9599
- "This is a critical positioning/display class. Review all usages before removal."
9600
- );
9601
- }
9602
- suggestions.push("Manual code review recommended before removing this class.");
9603
- } else if (impact.riskLevel === "medium") {
9604
- suggestions.push(
9605
- `This class is used in ${impact.totalComponents} components. Test each component after removal.`
9606
- );
9607
- if (impact.indirectUsage > 0) {
9608
- suggestions.push("Check for indirect usages via variants before removing.");
9609
- }
9610
- } else {
9611
- if (impact.totalComponents > 0) {
9612
- suggestions.push("Low risk: class is used in fewer than 5 components.");
9613
- } else {
9614
- suggestions.push("This class appears to be unused. Consider removing it.");
9615
- }
9616
- }
9617
- if (impact.estimatedSavings > 0) {
9618
- suggestions.push(`Estimated bundle size savings: ~${impact.estimatedSavings} bytes.`);
9619
- }
9620
- if (impact.bundleSizeBytes > 100) {
9621
- suggestions.push(
9622
- "This class has significant CSS bundle contribution. Removal will improve load times."
9623
- );
9490
+ const scores = native.calculateImpactScores(
9491
+ [normalizedClass],
9492
+ JSON.stringify(scanResult),
9493
+ "",
9494
+ 1,
9495
+ 0
9496
+ );
9497
+ if (!scores[0]?.usageCount) return [];
9498
+ const components = [];
9499
+ for (const file of scanResult.files) {
9500
+ if (!file.classes?.includes(normalizedClass)) continue;
9501
+ components.push({
9502
+ file: file.file,
9503
+ line: 1,
9504
+ column: 1,
9505
+ usageType: "direct"
9506
+ });
9624
9507
  }
9625
- return suggestions;
9508
+ return components;
9626
9509
  }
9510
+ /**
9511
+ * Cek apakah sebuah class dianggap "critical" (tidak boleh dihapus).
9512
+ *
9513
+ * Native: Rust `is_critical_class()` — O(n) pattern match di CRITICAL_PATTERNS.
9514
+ * Lebih cepat dari regex JS untuk daftar panjang karena no backtracking.
9515
+ *
9516
+ * @example
9517
+ * tracker.isCriticalClass("sr-only") // true
9518
+ * tracker.isCriticalClass("hidden") // true
9519
+ * tracker.isCriticalClass("bg-red-500") // false
9520
+ */
9627
9521
  isCriticalClass(className) {
9628
- const normalized = className.startsWith(".") ? className.slice(1) : className;
9629
- return this.criticalPatterns.some(
9630
- (pattern) => normalized === pattern || normalized.startsWith(`${pattern}:`)
9631
- );
9522
+ const native = getNativeEngineBinding();
9523
+ if (native?.isCriticalClass) {
9524
+ return native.isCriticalClass(className);
9525
+ }
9526
+ return false;
9632
9527
  }
9633
- calculateSavings(bundleSize, componentCount) {
9634
- const baseSavings = bundleSize;
9635
- const componentOverhead = componentCount * 50;
9636
- return Math.max(0, baseSavings - componentOverhead);
9528
+ /**
9529
+ * Generate human-readable suggestions berdasarkan impact analysis.
9530
+ *
9531
+ * Native: `generate_suggestions()` di Rust — pattern matching di CRITICAL_PATTERNS
9532
+ * + threshold-based risk categories.
9533
+ *
9534
+ * Biasanya dipanggil setelah `calculateImpact` yang sudah set riskLevel.
9535
+ */
9536
+ generateSuggestions(className, report) {
9537
+ const native = getNativeEngineBinding();
9538
+ if (native?.generateSuggestions) {
9539
+ return native.generateSuggestions(className, JSON.stringify(report));
9540
+ }
9541
+ return [];
9637
9542
  }
9638
9543
  createEmptyReport(className) {
9639
- const normalizedClass = className?.startsWith(".") ? className.slice(1) : className || "";
9640
9544
  return {
9641
- className: normalizedClass,
9545
+ className: className?.startsWith(".") ? className.slice(1) : className || "",
9642
9546
  totalComponents: 0,
9643
9547
  directUsage: 0,
9644
9548
  indirectUsage: 0,
@@ -9660,6 +9564,15 @@ var RuleId = class {
9660
9564
  return `R${this.value}`;
9661
9565
  }
9662
9566
  };
9567
+ var SelectorId = class {
9568
+ constructor(value) {
9569
+ this.value = value;
9570
+ }
9571
+ value;
9572
+ toString() {
9573
+ return `S${this.value}`;
9574
+ }
9575
+ };
9663
9576
  var VariantChainId = class {
9664
9577
  constructor(value) {
9665
9578
  this.value = value;
@@ -9717,322 +9630,308 @@ var ConditionId = class {
9717
9630
  return `C${this.value}`;
9718
9631
  }
9719
9632
  };
9720
- var propertyNames = /* @__PURE__ */ new Map();
9721
- var valueNames = /* @__PURE__ */ new Map();
9633
+ var CascadeResolutionId = class {
9634
+ constructor(value) {
9635
+ this.value = value;
9636
+ }
9637
+ value;
9638
+ toString() {
9639
+ return `R${this.value}`;
9640
+ }
9641
+ };
9642
+ var _propertyNamesFallback = /* @__PURE__ */ new Map();
9643
+ var _valueNamesFallback = /* @__PURE__ */ new Map();
9644
+ function registerPropertyName(id, name) {
9645
+ const native = getNativeEngineBinding();
9646
+ if (native?.registerPropertyName) {
9647
+ native.registerPropertyName(id.value, name);
9648
+ return;
9649
+ }
9650
+ _propertyNamesFallback.set(id.value, name);
9651
+ }
9652
+ function registerValueName(id, name) {
9653
+ const native = getNativeEngineBinding();
9654
+ if (native?.registerValueName) {
9655
+ native.registerValueName(id.value, name);
9656
+ return;
9657
+ }
9658
+ _valueNamesFallback.set(id.value, name);
9659
+ }
9722
9660
  function propertyIdToString(id) {
9723
- return propertyNames.get(id.value) ?? `P${id.value}`;
9661
+ const native = getNativeEngineBinding();
9662
+ if (native?.propertyIdToString) {
9663
+ return native.propertyIdToString(id.value);
9664
+ }
9665
+ return _propertyNamesFallback.get(id.value) ?? `P${id.value}`;
9724
9666
  }
9725
9667
  function valueIdToString(id) {
9726
- return valueNames.get(id.value) ?? `V${id.value}`;
9727
- }
9728
- function createFingerprint(parts) {
9668
+ const native = getNativeEngineBinding();
9669
+ if (native?.valueIdToString) {
9670
+ return native.valueIdToString(id.value);
9671
+ }
9672
+ return _valueNamesFallback.get(id.value) ?? `V${id.value}`;
9673
+ }
9674
+ var CascadeStage = /* @__PURE__ */ ((CascadeStage2) => {
9675
+ CascadeStage2[CascadeStage2["Origin"] = 0] = "Origin";
9676
+ CascadeStage2[CascadeStage2["Layer"] = 1] = "Layer";
9677
+ CascadeStage2[CascadeStage2["Importance"] = 2] = "Importance";
9678
+ CascadeStage2[CascadeStage2["Specificity"] = 3] = "Specificity";
9679
+ CascadeStage2[CascadeStage2["Order"] = 4] = "Order";
9680
+ return CascadeStage2;
9681
+ })(CascadeStage || {});
9682
+ function createFingerprintFallback(parts) {
9729
9683
  const hash = parts.reduce(
9730
9684
  (acc, part) => part.split("").reduce((h, char) => (h << 5) - h + char.charCodeAt(0) & h, acc),
9731
9685
  0
9732
9686
  );
9733
9687
  return Math.abs(hash).toString(36);
9734
9688
  }
9689
+ function createFingerprint(parts) {
9690
+ const native = getNativeEngineBinding();
9691
+ if (native?.createFingerprint) {
9692
+ return native.createFingerprint(parts);
9693
+ }
9694
+ return createFingerprintFallback(parts);
9695
+ }
9735
9696
 
9736
9697
  // packages/domain/engine/src/reverseLookup.ts
9737
- var ReverseLookup = class _ReverseLookup {
9738
- parsedCache = /* @__PURE__ */ new Map();
9739
- static MAX_CACHE_SIZE = 1e3;
9740
- /** Jumlah karakter total yang disimpan di cache (approx) */
9741
- cacheSizeBytes = 0;
9742
- static MAX_CACHE_BYTES = 10 * 1024 * 1024;
9743
- // 10MB
9744
- parseCSS(css) {
9745
- const cached = this.parsedCache.get(css);
9746
- if (cached) {
9747
- return cached;
9748
- }
9749
- try {
9750
- const native = (() => {
9751
- try {
9752
- return getNativeEngineBinding();
9753
- } catch {
9754
- return null;
9755
- }
9756
- })();
9757
- if (native?.parseCssRulesNative) {
9758
- const raw = native.parseCssRulesNative(css);
9759
- const rules2 = (raw ?? []).map((r) => ({
9760
- className: r.className,
9761
- property: r.property,
9762
- value: r.value,
9763
- specificity: r.specificity,
9764
- source: { file: "", line: 0, column: 0 },
9765
- isImportant: r.isImportant,
9766
- variants: r.variants,
9767
- isOverride: false
9768
- }));
9769
- this.pruneCache();
9770
- this.parsedCache.set(css, rules2);
9771
- return rules2;
9772
- }
9773
- } catch {
9774
- }
9775
- const rules = [];
9776
- const classMap = /* @__PURE__ */ new Map();
9777
- const selectorRegex = /\.([a-zA-Z_][a-zA-Z0-9_-]*)/g;
9778
- const propertyRegex = /([a-zA-Z-]+)\s*:\s*([^;]+)/g;
9779
- const importantRegex = /!important\s*;?\s*$/;
9780
- const lines = css.split("\n");
9781
- const columnState = { offset: 0 };
9782
- for (const [i, line] of lines.entries()) {
9783
- const lineEnd = columnState.offset + line.length + 1;
9784
- for (const match of line.matchAll(selectorRegex)) {
9785
- const className = match[1];
9786
- const selectorStart = match.index;
9787
- const lineColumn = selectorStart + 1;
9788
- if (!classMap.has(className)) {
9789
- classMap.set(className, /* @__PURE__ */ new Map());
9790
- }
9791
- const braceMatch = css.indexOf("{", lineEnd - 1);
9792
- if (braceMatch !== -1) {
9793
- const closingBraceMatch = this.findClosingBrace(css, braceMatch);
9794
- const ruleContent = css.substring(braceMatch + 1, closingBraceMatch);
9795
- const variants = [];
9796
- const variantMatch = className.match(/^(.+?)(?::([a-zA-Z0-9_-]+))?$/);
9797
- if (variantMatch?.[2]) {
9798
- variants.push(variantMatch[2]);
9799
- }
9800
- const specificity = this.calculateSpecificity(className);
9801
- const source = {
9802
- file: "inline",
9803
- line: i + 1,
9804
- column: lineColumn
9805
- };
9806
- for (const propMatch of ruleContent.matchAll(propertyRegex)) {
9807
- const property = propMatch[1].trim();
9808
- const rawValue = propMatch[2].trim();
9809
- const isImportant = importantRegex.test(rawValue);
9810
- const value = isImportant ? rawValue.replace(importantRegex, "").trim() : rawValue;
9811
- const rule = {
9812
- className,
9813
- property,
9814
- value,
9815
- specificity,
9816
- source,
9817
- isImportant,
9818
- variants,
9819
- isOverride: false
9820
- };
9821
- rules.push(rule);
9822
- const classRules = classMap.get(className);
9823
- const existingProp = classRules.get(property);
9824
- if (existingProp) {
9825
- rule.isOverride = true;
9826
- }
9827
- classRules.set(property, rule);
9828
- }
9829
- }
9830
- }
9831
- columnState.offset = lineEnd;
9832
- }
9833
- this.pruneCache();
9834
- this.parsedCache.set(css, rules);
9835
- return rules;
9698
+ function getNative() {
9699
+ const native = getNativeEngineBinding();
9700
+ if (!native?.reverseLookupFromCss || !native?.reverseLookupByProperty || !native?.reverseLookupFindDependents) {
9701
+ throw new Error(
9702
+ "FATAL: Native bindings 'reverseLookupFromCss', 'reverseLookupByProperty', 'reverseLookupFindDependents' are required but not available.\nBuild the native Rust module: npm run build:rust"
9703
+ );
9836
9704
  }
9837
- findClosingBrace(css, start) {
9838
- let depth = 1;
9839
- for (let pos = start + 1; pos < css.length; pos++) {
9840
- const char = css[pos];
9841
- if (char === "{") depth++;
9842
- else if (char === "}") {
9843
- depth--;
9844
- if (depth === 0) return pos;
9845
- }
9846
- }
9847
- return css.length;
9705
+ return native;
9706
+ }
9707
+ function normaliseNativeResults(raw) {
9708
+ return raw.map((r) => ({
9709
+ property: r.property,
9710
+ value: r.value,
9711
+ usedInClasses: r.usedInClasses.map((u) => ({
9712
+ className: u.className,
9713
+ source: { file: "", line: 0, column: 0 },
9714
+ specificity: u.specificity,
9715
+ isOverride: u.isOverride,
9716
+ variants: u.variants
9717
+ }))
9718
+ }));
9719
+ }
9720
+ var ReverseLookup = class {
9721
+ fromCSS(cssProperty, cssValue, css) {
9722
+ if (!css || !cssProperty) return [];
9723
+ return normaliseNativeResults(getNative().reverseLookupFromCss(css, cssProperty, cssValue));
9848
9724
  }
9849
- calculateSpecificity(className) {
9850
- const pseudoClasses = className.match(/:[a-zA-Z-]+/g) || [];
9851
- const attributes = className.match(/\[[^\]]+\]/g) || [];
9852
- const pseudoElements = className.match(/::[a-zA-Z-]+/g) || [];
9853
- return 1 + pseudoClasses.length * 10 + attributes.length * 10 + pseudoElements.length * 100;
9725
+ findByProperty(property, css) {
9726
+ if (!css || !property) return [];
9727
+ return normaliseNativeResults(getNative().reverseLookupByProperty(css, property));
9854
9728
  }
9855
- fromCSS(cssProperty, cssValue, css) {
9856
- if (!css || !cssProperty) {
9857
- return [];
9858
- }
9859
- const rules = this.parseCSS(css);
9860
- const normalizedProperty = cssProperty.toLowerCase();
9861
- const normalizedValue = cssValue.toLowerCase().trim();
9862
- const usages = [];
9863
- for (const rule of rules) {
9864
- if (rule.property.toLowerCase() !== normalizedProperty) {
9865
- continue;
9866
- }
9867
- const ruleValueLower = rule.value.toLowerCase().trim();
9868
- if (ruleValueLower !== normalizedValue && !ruleValueLower.includes(normalizedValue)) {
9869
- continue;
9870
- }
9871
- usages.push({
9872
- className: rule.className,
9873
- source: rule.source,
9874
- specificity: rule.specificity,
9875
- isOverride: rule.isOverride || false,
9876
- variants: rule.variants
9877
- });
9878
- }
9879
- if (usages.length === 0) {
9880
- return [];
9881
- }
9882
- return [{ property: normalizedProperty, value: cssValue, usedInClasses: usages }];
9729
+ findDependents(className, css) {
9730
+ if (!css || !className) return [];
9731
+ return getNative().reverseLookupFindDependents(css, className);
9883
9732
  }
9884
9733
  fromBundle(className, css) {
9885
- if (!css || !className) {
9886
- return [];
9734
+ if (!css || !className) return [];
9735
+ const native = getNativeEngineBinding();
9736
+ if (!native?.parseCssRules) {
9737
+ throw new Error("FATAL: Native binding 'parseCssRules' is required but not available.");
9887
9738
  }
9888
- const rules = this.parseCSS(css);
9739
+ const raw = native.parseCssRules(css);
9889
9740
  const results = [];
9890
- for (const rule of rules) {
9891
- if (rule.className === className || rule.className.startsWith(`${className}:`)) {
9892
- const ruleIR = {
9893
- id: { value: results.length },
9894
- selector: { value: 0 },
9895
- variantChain: { value: 0 },
9896
- property: { value: 0 },
9897
- value: { value: 0 },
9898
- origin: 2,
9899
- importance: rule.isImportant ? 1 : 0,
9900
- layer: null,
9901
- layerOrder: 0,
9902
- specificity: rule.specificity,
9903
- condition: null,
9904
- conditionResult: 0,
9905
- insertionOrder: results.length,
9906
- fingerprint: "",
9907
- source: rule.source
9908
- };
9909
- results.push(ruleIR);
9910
- }
9741
+ for (const rule of raw ?? []) {
9742
+ if (rule.className !== className && !rule.className.startsWith(`${className}:`)) continue;
9743
+ results.push({
9744
+ id: { value: results.length },
9745
+ selector: { value: 0 },
9746
+ variantChain: { value: 0 },
9747
+ property: { value: 0 },
9748
+ value: { value: 0 },
9749
+ origin: 2,
9750
+ importance: rule.isImportant ? 1 : 0,
9751
+ layer: null,
9752
+ layerOrder: 0,
9753
+ specificity: rule.specificity,
9754
+ condition: null,
9755
+ conditionResult: 0,
9756
+ insertionOrder: results.length,
9757
+ fingerprint: "",
9758
+ source: { file: "", line: 0, column: 0 }
9759
+ });
9911
9760
  }
9912
9761
  return results;
9913
9762
  }
9914
- findDependents(className, css) {
9915
- if (!css || !className) {
9916
- return [];
9917
- }
9918
- const rules = this.parseCSS(css);
9919
- const dependents = /* @__PURE__ */ new Set();
9920
- const classParts = className.split(":");
9921
- const baseClass = classParts[0];
9922
- for (const rule of rules) {
9923
- const ruleBaseClass = rule.className.split(":")[0];
9924
- if (ruleBaseClass === baseClass && rule.className !== className) {
9925
- dependents.add(rule.className);
9926
- }
9927
- if (rule.className.includes(baseClass) && rule.className !== className) {
9928
- const isVariant = rule.className.includes(":");
9929
- if (isVariant && !rule.className.startsWith(`${className}:`)) {
9930
- dependents.add(rule.className);
9931
- }
9932
- }
9933
- }
9934
- return Array.from(dependents);
9763
+ clearCache() {
9764
+ getNativeEngineBinding()?.reverseLookupClearCache?.();
9935
9765
  }
9936
- findByProperty(property, css) {
9937
- if (!css || !property) {
9938
- return [];
9939
- }
9940
- const rules = this.parseCSS(css);
9941
- const normalizedProperty = property.toLowerCase();
9942
- const valueMap = /* @__PURE__ */ new Map();
9943
- for (const rule of rules) {
9944
- if (rule.property.toLowerCase() !== normalizedProperty) {
9945
- continue;
9946
- }
9947
- const classUsage = {
9948
- className: rule.className,
9949
- source: rule.source,
9950
- specificity: rule.specificity,
9951
- isOverride: rule.isOverride || false,
9952
- variants: rule.variants
9953
- };
9954
- let usages = valueMap.get(rule.value);
9955
- if (!usages) {
9956
- usages = [];
9957
- valueMap.set(rule.value, usages);
9958
- }
9959
- usages.push(classUsage);
9960
- }
9961
- const results = [];
9962
- for (const [value, usedInClasses] of valueMap) {
9963
- results.push({ property: normalizedProperty, value, usedInClasses });
9964
- }
9965
- return results;
9766
+ get cacheSize() {
9767
+ return getNativeEngineBinding()?.reverseLookupCacheSize?.() ?? 0;
9768
+ }
9769
+ };
9770
+
9771
+ // packages/domain/engine/src/resolver.ts
9772
+ function toNativeInput(rule) {
9773
+ return {
9774
+ id: rule.id.value,
9775
+ property: rule.property.value,
9776
+ origin: rule.origin,
9777
+ importance: rule.importance,
9778
+ layerOrder: rule.layerOrder,
9779
+ specificity: rule.specificity,
9780
+ conditionResult: rule.conditionResult,
9781
+ insertionOrder: rule.insertionOrder
9782
+ };
9783
+ }
9784
+ function callResolveCascade(rules) {
9785
+ const native = getNativeEngineBinding();
9786
+ if (!native.resolveCascade) {
9787
+ throw new Error(
9788
+ "FATAL: Native binding 'resolveCascade' is required but not available.\nThis function requires native Rust bindings.\n\nResolution steps:\n1. Build the native Rust module: npm run build:rust"
9789
+ );
9790
+ }
9791
+ const json = JSON.stringify(rules.map(toNativeInput));
9792
+ return JSON.parse(native.resolveCascade(json));
9793
+ }
9794
+ function buildResolutionsMap(nativeResult, rules, styleGraph) {
9795
+ const propertyIdMap = /* @__PURE__ */ new Map();
9796
+ for (const rule of rules) {
9797
+ if (!propertyIdMap.has(rule.property.value)) {
9798
+ propertyIdMap.set(rule.property.value, rule.property);
9799
+ }
9800
+ }
9801
+ const resolvedProperties = /* @__PURE__ */ new Map();
9802
+ for (const res of nativeResult.resolutions) {
9803
+ const propertyId = propertyIdMap.get(res.propertyId);
9804
+ if (!propertyId) continue;
9805
+ const winner = { value: res.winnerId };
9806
+ const losers = res.loserIds.map((v) => ({ value: v }));
9807
+ const existing = styleGraph.ruleConflicts.get(winner) ?? [];
9808
+ styleGraph.ruleConflicts.set(winner, [...existing, ...losers.filter((l) => !existing.some((e) => e.value === l.value))]);
9809
+ resolvedProperties.set(propertyId, {
9810
+ id: new CascadeResolutionId(res.id),
9811
+ property: propertyId,
9812
+ winner,
9813
+ losers,
9814
+ reason: { causes: res.causes, finalDecision: res.finalDecision },
9815
+ stage: res.stage
9816
+ });
9817
+ }
9818
+ return resolvedProperties;
9819
+ }
9820
+ var CascadeResolver = class {
9821
+ rules = /* @__PURE__ */ new Map();
9822
+ classRules = /* @__PURE__ */ new Map();
9823
+ styleGraph = { ruleConflicts: /* @__PURE__ */ new Map() };
9824
+ addRule(rule) {
9825
+ this.rules.set(rule.id, rule);
9826
+ }
9827
+ addRules(rules) {
9828
+ for (const rule of rules) this.addRule(rule);
9829
+ }
9830
+ registerClass(className, ruleIds) {
9831
+ this.classRules.set(className, ruleIds);
9832
+ }
9833
+ getRule(ruleId) {
9834
+ return this.rules.get(ruleId);
9835
+ }
9836
+ getClassRules(className) {
9837
+ return this.classRules.get(className);
9838
+ }
9839
+ getStyleGraph() {
9840
+ return this.styleGraph;
9966
9841
  }
9967
9842
  /**
9968
- * Kosongkan seluruh parsed cache.
9969
- * Panggil ini saat CSS berubah (watch mode) atau saat memory pressure.
9843
+ * Resolve cascade for a specific class.
9844
+ * Delegates sort + winner selection to Rust.
9970
9845
  */
9971
- clearCache() {
9972
- this.parsedCache.clear();
9973
- this.cacheSizeBytes = 0;
9846
+ resolveByClassName(className) {
9847
+ const ruleIds = this.classRules.get(className);
9848
+ if (!ruleIds || ruleIds.length === 0) return null;
9849
+ const classRules = ruleIds.map((id) => this.rules.get(id)).filter((r) => r !== void 0);
9850
+ if (classRules.length === 0) return null;
9851
+ const nativeResult = callResolveCascade(classRules);
9852
+ return { resolvedProperties: buildResolutionsMap(nativeResult, classRules, this.styleGraph) };
9974
9853
  }
9975
9854
  /**
9976
- * Hapus entri cache lama sampai di bawah threshold.
9977
- * Dipakai oleh parseCSS secara internal.
9855
+ * Resolve cascade for all rules.
9856
+ * Delegates sort + winner selection to Rust.
9978
9857
  */
9979
- pruneCache() {
9980
- while ((this.parsedCache.size >= _ReverseLookup.MAX_CACHE_SIZE || this.cacheSizeBytes >= _ReverseLookup.MAX_CACHE_BYTES) && this.parsedCache.size > 0) {
9981
- const firstKey = this.parsedCache.keys().next().value;
9982
- if (firstKey === void 0) break;
9983
- const removed = this.parsedCache.get(firstKey);
9984
- this.parsedCache.delete(firstKey);
9985
- this.cacheSizeBytes -= firstKey.length + (removed?.length ?? 0) * 100;
9986
- if (this.cacheSizeBytes < 0) this.cacheSizeBytes = 0;
9987
- }
9858
+ resolveAllProperties() {
9859
+ const allRules = Array.from(this.rules.values());
9860
+ if (allRules.length === 0) return /* @__PURE__ */ new Map();
9861
+ const nativeResult = callResolveCascade(allRules);
9862
+ return buildResolutionsMap(nativeResult, allRules, this.styleGraph);
9988
9863
  }
9989
- /** Cache size untuk observability/diagnostics */
9990
- get cacheSize() {
9991
- return this.parsedCache.size;
9864
+ /**
9865
+ * Resolve cascade for a specific set of rule IDs.
9866
+ */
9867
+ resolveForClass(classRuleIds) {
9868
+ const classRules = classRuleIds.map((id) => this.rules.get(id)).filter((r) => r !== void 0);
9869
+ if (classRules.length === 0) return /* @__PURE__ */ new Map();
9870
+ const nativeResult = callResolveCascade(classRules);
9871
+ return buildResolutionsMap(nativeResult, classRules, this.styleGraph);
9872
+ }
9873
+ /**
9874
+ * Resolve cascade for a single property bucket.
9875
+ */
9876
+ resolveProperty(property) {
9877
+ const bucketRuleIds = Array.from(this.rules.values()).filter((r) => r.property.value === property.value);
9878
+ if (bucketRuleIds.length === 0) return null;
9879
+ const nativeResult = callResolveCascade(bucketRuleIds);
9880
+ const resolved = buildResolutionsMap(nativeResult, bucketRuleIds, this.styleGraph);
9881
+ return resolved.get(property) ?? null;
9882
+ }
9883
+ getResolution(_id) {
9884
+ return void 0;
9992
9885
  }
9993
9886
  };
9994
9887
 
9995
- // packages/infrastructure/cli/src/utils/traceService.ts
9996
- init_src2();
9997
- init_src();
9998
- var createIdGenerator = () => {
9999
- const _counters = {
10000
- ruleId: 0,
10001
- selectorId: 0,
10002
- propertyId: 0,
10003
- valueId: 0,
10004
- layerId: 0,
10005
- conditionId: 0,
10006
- insertionOrder: 0
10007
- };
10008
- const generateRuleId = () => new RuleId(_counters.ruleId++);
10009
- const generateSelectorId = () => new RuleId(_counters.selectorId++);
10010
- const generatePropertyId = (propertyName) => new PropertyId(_counters.propertyId++, propertyName);
10011
- const generateValueId = (valueName) => new ValueId(_counters.valueId++, valueName);
10012
- const generateLayerId = () => new LayerId(_counters.layerId++);
10013
- const generateConditionId = () => new ConditionId(_counters.conditionId++);
10014
- const getNextInsertionOrder = () => _counters.insertionOrder++;
10015
- const reset = () => {
10016
- _counters.ruleId = 0;
10017
- _counters.selectorId = 0;
10018
- _counters.propertyId = 0;
10019
- _counters.valueId = 0;
10020
- _counters.layerId = 0;
10021
- _counters.conditionId = 0;
10022
- _counters.insertionOrder = 0;
9888
+ // packages/domain/engine/src/cssToIr.ts
9889
+ function createIdGenerator() {
9890
+ const state = {
9891
+ ruleIdCounter: 0,
9892
+ selectorIdCounter: 0,
9893
+ propertyIdCounter: 0,
9894
+ valueIdCounter: 0,
9895
+ layerIdCounter: 0,
9896
+ conditionIdCounter: 0,
9897
+ insertionOrderCounter: 0
10023
9898
  };
10024
9899
  return {
10025
- generateRuleId,
10026
- generateSelectorId,
10027
- generatePropertyId,
10028
- generateValueId,
10029
- generateLayerId,
10030
- generateConditionId,
10031
- getNextInsertionOrder,
10032
- reset
9900
+ generateRuleId: () => new RuleId(state.ruleIdCounter++),
9901
+ generateSelectorId: () => new SelectorId(state.selectorIdCounter++),
9902
+ generatePropertyId: (name) => {
9903
+ const id = new PropertyId(state.propertyIdCounter++);
9904
+ registerPropertyName(id, name);
9905
+ return id;
9906
+ },
9907
+ generateValueId: (name) => {
9908
+ const id = new ValueId(state.valueIdCounter++);
9909
+ registerValueName(id, name);
9910
+ return id;
9911
+ },
9912
+ generateLayerId: () => new LayerId(state.layerIdCounter++),
9913
+ generateConditionId: () => new ConditionId(state.conditionIdCounter++),
9914
+ getNextInsertionOrder: () => state.insertionOrderCounter++,
9915
+ reset: () => {
9916
+ state.ruleIdCounter = 0;
9917
+ state.selectorIdCounter = 0;
9918
+ state.propertyIdCounter = 0;
9919
+ state.valueIdCounter = 0;
9920
+ state.layerIdCounter = 0;
9921
+ state.conditionIdCounter = 0;
9922
+ state.insertionOrderCounter = 0;
9923
+ }
10033
9924
  };
10034
- };
10035
- var idGenerator = createIdGenerator();
9925
+ }
9926
+ var _defaultIdGen = createIdGenerator();
9927
+ var generateRuleId = () => _defaultIdGen.generateRuleId();
9928
+ var generateSelectorId = () => _defaultIdGen.generateSelectorId();
9929
+ var generatePropertyId = (name) => _defaultIdGen.generatePropertyId(name);
9930
+ var generateValueId = (name) => _defaultIdGen.generateValueId(name);
9931
+ var generateLayerId = () => _defaultIdGen.generateLayerId();
9932
+ var generateConditionId = () => _defaultIdGen.generateConditionId();
9933
+ var getNextInsertionOrder = () => _defaultIdGen.getNextInsertionOrder();
9934
+ var resetIdGenerator = () => _defaultIdGen.reset();
10036
9935
  var layerMap = /* @__PURE__ */ new Map();
10037
9936
  var layerOrderMap = /* @__PURE__ */ new Map();
10038
9937
  var LAYER_ORDER = {
@@ -10044,109 +9943,41 @@ var LAYER_ORDER = {
10044
9943
  function getOrCreateLayerId(layerName) {
10045
9944
  const existing = layerMap.get(layerName);
10046
9945
  if (existing) return existing;
10047
- const order = LAYER_ORDER[layerName] ?? 4;
10048
- const layerId = idGenerator.generateLayerId();
9946
+ const layerId = generateLayerId();
10049
9947
  layerMap.set(layerName, layerId);
10050
- layerOrderMap.set(layerName, order);
9948
+ layerOrderMap.set(layerName, LAYER_ORDER[layerName] ?? 4);
10051
9949
  return layerId;
10052
9950
  }
10053
- function calculateSpecificity(selector) {
10054
- const classCount = selector.className.split(":").length * 10;
10055
- const pseudoCount = selector.pseudoClasses.length * 10;
10056
- const mediaCount = selector.mediaQuery ? 1e3 : 0;
10057
- return classCount + pseudoCount + mediaCount;
10058
- }
10059
- function parseSelector(selectorText) {
10060
- const mediaMatch = selectorText.match(/^@media[^{]+\{(.+)$/);
10061
- const mediaQuery = mediaMatch ? mediaMatch[0] : null;
10062
- const baseClass = (mediaMatch ? mediaMatch[1].trim() : selectorText).startsWith(".") ? (mediaMatch ? mediaMatch[1].trim() : selectorText).slice(1) : mediaMatch ? mediaMatch[1].trim() : selectorText;
10063
- const escapedColon = /\\:/g;
10064
- const baseClassClean = baseClass.startsWith(".") ? baseClass.slice(1) : baseClass;
10065
- const baseClassFinal = baseClassClean.replace(escapedColon, "\u200B").split(":")[0].replace(/\u200B/g, ":");
10066
- const variantRegex = /^(hover|focus|active|visited|checked|disabled|required|optional|first|last|odd|even|before|after|placeholder|file|selection|backdrop|group|peer)/i;
10067
- const pseudoRegex = /^:([a-zA-Z-]+)$/;
10068
- const parts = baseClassFinal.split(":").slice(1);
10069
- const { variants, pseudoClasses } = parts.reduce(
10070
- (acc, part) => {
10071
- const normalized = `:${part}`;
10072
- if (variantRegex.test(part)) {
10073
- acc.variants.push(part);
10074
- } else if (pseudoRegex.test(normalized)) {
10075
- acc.pseudoClasses.push(normalized);
10076
- } else {
10077
- acc.variants.push(part);
10078
- }
10079
- return acc;
10080
- },
10081
- { variants: [], pseudoClasses: [] }
10082
- );
10083
- return {
10084
- className: baseClassFinal,
10085
- variants,
10086
- pseudoClasses,
10087
- mediaQuery
10088
- };
10089
- }
10090
- function parseDeclaration(block) {
10091
- const declarations = [];
10092
- for (const match of block.matchAll(/([a-zA-Z-]+)\s*:\s*([^;!]+)(!important)?/g)) {
10093
- const property = match[1].trim();
10094
- const value = match[2].trim();
10095
- const important = match[3] !== void 0;
10096
- declarations.push({ property, value, important });
10097
- }
10098
- return declarations;
10099
- }
10100
- function parseRules(css) {
10101
- const rules = [];
10102
- for (const match of css.matchAll(/([^{}]+)\s*\{([^{}]*)\}/g)) {
10103
- const selectorText = match[1].trim();
10104
- const declarationBlock = match[2].trim();
10105
- if (selectorText.startsWith("@")) {
10106
- continue;
10107
- }
10108
- const parsedSelector = parseSelector(selectorText);
10109
- const declarations = parseDeclaration(declarationBlock);
10110
- for (const decl of declarations) {
10111
- rules.push({
10112
- selector: parsedSelector,
10113
- property: decl.property,
10114
- value: decl.value,
10115
- important: decl.important
10116
- });
10117
- }
10118
- }
10119
- return rules;
10120
- }
10121
- function detectLayerFromSelector(className) {
10122
- const layerPrefixes = ["tw-", "tailwind-"];
10123
- for (const prefix of layerPrefixes) {
10124
- if (className.startsWith(prefix)) {
10125
- return "tailwind";
10126
- }
10127
- }
9951
+ function detectLayerFromClassName(className) {
9952
+ if (className.startsWith("tw-") || className.startsWith("tailwind-")) return "tailwind";
10128
9953
  return null;
10129
9954
  }
10130
- function parseCssToIr(css, prefix = "") {
10131
- idGenerator.reset();
9955
+ function parseCssToIr(css, options = {}) {
9956
+ resetIdGenerator();
10132
9957
  layerMap.clear();
10133
9958
  layerOrderMap.clear();
9959
+ const native = getNativeEngineBinding();
9960
+ if (!native?.parseCssRules) {
9961
+ throw new Error("FATAL: Native binding 'parseCssRules' is required but not available.");
9962
+ }
9963
+ const prefix = options.prefix ?? "";
10134
9964
  const rules = [];
10135
9965
  const classToRuleIds = /* @__PURE__ */ new Map();
10136
- const parsedRules = parseRules(css);
10137
- for (const parsedRule of parsedRules) {
10138
- const className = prefix + parsedRule.selector.className;
10139
- const specificity = calculateSpecificity(parsedRule.selector);
10140
- const layerName = detectLayerFromSelector(className);
9966
+ const parsed = native.parseCssRules(css);
9967
+ for (const r of parsed) {
9968
+ const className = prefix + r.className;
9969
+ r.variants.length > 0;
9970
+ const layerName = detectLayerFromClassName(className);
10141
9971
  const layer = layerName ? getOrCreateLayerId(layerName) : null;
10142
9972
  const layerOrder = layerName ? layerOrderMap.get(layerName) ?? 4 : 4;
10143
- const selectorId = idGenerator.generateSelectorId();
10144
- const propertyId = idGenerator.generatePropertyId(parsedRule.property);
10145
- const valueId = idGenerator.generateValueId(parsedRule.value);
10146
- const conditionId = parsedRule.selector.mediaQuery ? idGenerator.generateConditionId() : null;
10147
- const conditionResult = parsedRule.selector.mediaQuery ? 2 /* Unknown */ : 2 /* Unknown */;
10148
- const fingerprint = createFingerprint([className, parsedRule.property, parsedRule.value]);
10149
- const ruleId = idGenerator.generateRuleId();
9973
+ const selectorId = generateSelectorId();
9974
+ const propertyId = generatePropertyId(r.property);
9975
+ const valueId = generateValueId(r.value);
9976
+ const hasMedia = r.variants.some((v) => v.startsWith("@") || v === "dark" || v === "print");
9977
+ const conditionId = hasMedia ? generateConditionId() : null;
9978
+ const conditionResult = hasMedia ? 2 /* Unknown */ : 2 /* Unknown */;
9979
+ const ruleId = generateRuleId();
9980
+ const fingerprint = createFingerprint([className, r.property, r.value]);
10150
9981
  const rule = {
10151
9982
  id: ruleId,
10152
9983
  selector: selectorId,
@@ -10154,117 +9985,58 @@ function parseCssToIr(css, prefix = "") {
10154
9985
  property: propertyId,
10155
9986
  value: valueId,
10156
9987
  origin: 2 /* AuthorNormal */,
10157
- importance: parsedRule.important ? 1 /* Important */ : 0 /* Normal */,
9988
+ importance: r.isImportant ? 1 /* Important */ : 0 /* Normal */,
10158
9989
  layer,
10159
9990
  layerOrder,
10160
- specificity,
9991
+ specificity: r.specificity,
9992
+ // from native — no JS recalculation
10161
9993
  condition: conditionId,
10162
9994
  conditionResult,
10163
- insertionOrder: idGenerator.getNextInsertionOrder(),
9995
+ insertionOrder: getNextInsertionOrder(),
10164
9996
  fingerprint,
10165
- source: {
10166
- file: "",
10167
- line: 1,
10168
- column: 1
10169
- }
9997
+ source: { file: "", line: 1, column: 1 }
10170
9998
  };
10171
9999
  rules.push(rule);
10172
- const existingRuleIds = classToRuleIds.get(className) || [];
10173
- existingRuleIds.push(ruleId);
10174
- classToRuleIds.set(className, existingRuleIds);
10000
+ const existing = classToRuleIds.get(className) ?? [];
10001
+ existing.push(ruleId);
10002
+ classToRuleIds.set(className, existing);
10175
10003
  }
10176
10004
  return { rules, classToRuleIds };
10177
10005
  }
10178
- var CascadeResolver = class {
10179
- propertyBuckets = /* @__PURE__ */ new Map();
10180
- rules = /* @__PURE__ */ new Map();
10181
- classRules = /* @__PURE__ */ new Map();
10182
- addRule(rule) {
10183
- this.rules.set(rule.id, rule);
10184
- const property = rule.property;
10185
- const existingBucket = this.propertyBuckets.get(property);
10186
- if (!existingBucket) {
10187
- this.propertyBuckets.set(property, {
10188
- property,
10189
- rules: [rule.id]
10190
- });
10191
- } else {
10192
- this.propertyBuckets.set(property, {
10193
- ...existingBucket,
10194
- rules: [...existingBucket.rules, rule.id]
10195
- });
10196
- }
10197
- }
10198
- addRules(rules) {
10199
- for (const rule of rules) {
10200
- this.addRule(rule);
10201
- }
10202
- }
10203
- getRule(ruleId) {
10204
- return this.rules.get(ruleId);
10205
- }
10206
- registerClass(className, ruleIds) {
10207
- this.classRules.set(className, ruleIds);
10208
- }
10209
- getClassRules(className) {
10210
- return this.classRules.get(className);
10211
- }
10212
- resolveByClassName(className) {
10213
- const ruleIds = this.classRules.get(className);
10214
- if (!ruleIds) {
10215
- return null;
10216
- }
10217
- const classRules = [];
10218
- for (const ruleId of ruleIds) {
10219
- const rule = this.rules.get(ruleId);
10220
- if (rule) {
10221
- classRules.push(rule);
10222
- }
10223
- }
10224
- const propertyMap = /* @__PURE__ */ new Map();
10225
- for (const rule of classRules) {
10226
- const existing = propertyMap.get(rule.property) || [];
10227
- existing.push(rule);
10228
- propertyMap.set(rule.property, existing);
10229
- }
10230
- const resolved = /* @__PURE__ */ new Map();
10231
- for (const [property, rules] of propertyMap) {
10232
- if (rules.length > 0) {
10233
- const activeRules = rules.filter((r) => r.conditionResult !== 1 /* Inactive */);
10234
- if (activeRules.length > 0) {
10235
- activeRules.sort((a, b) => {
10236
- const originDiff = b.origin - a.origin;
10237
- if (originDiff !== 0) return originDiff;
10238
- const layerDiff = b.layerOrder - a.layerOrder;
10239
- if (layerDiff !== 0) return layerDiff;
10240
- const importanceDiff = b.importance - a.importance;
10241
- if (importanceDiff !== 0) return importanceDiff;
10242
- const specificityDiff = b.specificity - a.specificity;
10243
- if (specificityDiff !== 0) return specificityDiff;
10244
- return b.insertionOrder - a.insertionOrder;
10245
- });
10246
- const winner = activeRules[0];
10247
- resolved.set(property, { winner: winner.id });
10248
- }
10249
- }
10250
- }
10251
- return { resolvedProperties: resolved };
10252
- }
10253
- };
10254
- function trace(className, resolver) {
10255
- const provenance = {
10006
+
10007
+ // packages/domain/engine/src/trace.ts
10008
+ function buildProvenanceChain(className) {
10009
+ return {
10010
+ className,
10256
10011
  source: { file: "", line: 0, column: 0 },
10257
10012
  variants: /* @__PURE__ */ new Map(),
10258
10013
  rules: /* @__PURE__ */ new Map()
10259
10014
  };
10015
+ }
10016
+ function formatCause(c) {
10017
+ switch (c.type) {
10018
+ case "LowerOrigin":
10019
+ return "lower origin";
10020
+ case "LowerLayer":
10021
+ return "lower layer";
10022
+ case "LowerImportance":
10023
+ return "lower importance";
10024
+ case "LowerSpecificity":
10025
+ return `specificity ${c.delta}`;
10026
+ case "EarlierOrder":
10027
+ return `earlier order ${c.delta}`;
10028
+ case "InactiveCondition":
10029
+ return "inactive condition";
10030
+ }
10031
+ }
10032
+ function trace(className, resolver) {
10033
+ const provenance = buildProvenanceChain(className);
10260
10034
  const classRuleIds = resolver.getClassRules(className);
10261
10035
  const allRules = [];
10262
10036
  if (classRuleIds) {
10263
10037
  for (const ruleId of classRuleIds) {
10264
10038
  const rule = resolver.getRule(ruleId);
10265
- if (rule) {
10266
- allRules.push(rule);
10267
- }
10039
+ if (rule) allRules.push(rule);
10268
10040
  }
10269
10041
  }
10270
10042
  for (const rules of provenance.rules.values()) {
@@ -10273,57 +10045,49 @@ function trace(className, resolver) {
10273
10045
  const rulesByProperty = /* @__PURE__ */ new Map();
10274
10046
  for (const rule of allRules) {
10275
10047
  const propKey = rule.property.toString();
10276
- if (!rulesByProperty.has(propKey)) {
10277
- rulesByProperty.set(propKey, []);
10278
- }
10279
- rulesByProperty.get(propKey).push(rule);
10048
+ const bucket = rulesByProperty.get(propKey) ?? [];
10049
+ bucket.push(rule);
10050
+ rulesByProperty.set(propKey, bucket);
10280
10051
  }
10052
+ const resolved = resolver.resolveByClassName(className);
10281
10053
  const ruleTraces = [];
10282
10054
  const conflictTraces = [];
10283
- for (const [property, rules] of rulesByProperty) {
10284
- if (rules.length === 0) continue;
10285
- const activeRules = rules.filter((r) => r.conditionResult !== 1 /* Inactive */);
10286
- if (activeRules.length === 0) continue;
10287
- activeRules.sort((a, b) => {
10288
- const originDiff = b.origin - a.origin;
10289
- if (originDiff !== 0) return originDiff;
10290
- const layerDiff = b.layerOrder - a.layerOrder;
10291
- if (layerDiff !== 0) return layerDiff;
10292
- const importanceDiff = b.importance - a.importance;
10293
- if (importanceDiff !== 0) return importanceDiff;
10294
- const specificityDiff = b.specificity - a.specificity;
10295
- if (specificityDiff !== 0) return specificityDiff;
10296
- return b.insertionOrder - a.insertionOrder;
10297
- });
10298
- const winnerRule = activeRules[0];
10299
- const losers = activeRules.slice(1);
10300
- ruleTraces.push({
10301
- property,
10302
- value: winnerRule.value.toString(),
10303
- applied: true,
10304
- reason: null,
10305
- source: winnerRule.source,
10306
- specificity: winnerRule.specificity
10307
- });
10308
- for (const loserRule of losers) {
10309
- ruleTraces.push({
10310
- property,
10311
- value: loserRule.value.toString(),
10312
- applied: false,
10313
- reason: "lower specificity",
10314
- source: loserRule.source,
10315
- specificity: loserRule.specificity
10316
- });
10317
- conflictTraces.push({
10318
- property,
10319
- winner: winnerRule.value.toString(),
10320
- loser: loserRule.value.toString(),
10321
- stage: "Specificity",
10322
- causes: ["lower specificity"]
10323
- });
10055
+ if (resolved) {
10056
+ for (const [propId, resolution] of resolved.resolvedProperties) {
10057
+ const property = propId.toString();
10058
+ const rules = rulesByProperty.get(property) ?? [];
10059
+ const winnerRule = rules.find((r) => r.id.value === resolution.winner.value);
10060
+ if (winnerRule) {
10061
+ ruleTraces.push({
10062
+ property,
10063
+ value: winnerRule.value.toString(),
10064
+ applied: true,
10065
+ reason: null,
10066
+ source: winnerRule.source,
10067
+ specificity: winnerRule.specificity
10068
+ });
10069
+ }
10070
+ for (const loserId of resolution.losers) {
10071
+ const loserRule = rules.find((r) => r.id.value === loserId.value);
10072
+ if (!loserRule) continue;
10073
+ ruleTraces.push({
10074
+ property,
10075
+ value: loserRule.value.toString(),
10076
+ applied: false,
10077
+ reason: resolution.reason.finalDecision,
10078
+ source: loserRule.source,
10079
+ specificity: loserRule.specificity
10080
+ });
10081
+ conflictTraces.push({
10082
+ property,
10083
+ winner: winnerRule?.value.toString() ?? "",
10084
+ loser: loserRule.value.toString(),
10085
+ stage: CascadeStage[resolution.stage],
10086
+ causes: resolution.reason.causes.map(formatCause)
10087
+ });
10088
+ }
10324
10089
  }
10325
10090
  }
10326
- const resolved = resolver.resolveByClassName(className);
10327
10091
  const finalStyle = [];
10328
10092
  if (resolved) {
10329
10093
  for (const [propId, resolution] of resolved.resolvedProperties) {
@@ -10343,6 +10107,30 @@ function trace(className, resolver) {
10343
10107
  finalStyle
10344
10108
  };
10345
10109
  }
10110
+
10111
+ // packages/infrastructure/cli/src/utils/traceService.ts
10112
+ init_src2();
10113
+ init_src();
10114
+ function safeToString(value) {
10115
+ if (value === null || value === void 0) return "";
10116
+ if (typeof value === "string") return value;
10117
+ if (typeof value === "number") return String(value);
10118
+ if (typeof value === "object") {
10119
+ const obj = value;
10120
+ if (typeof obj.name === "string" && obj.name.length > 0) return obj.name;
10121
+ if (obj.value !== void 0) return String(obj.value);
10122
+ const toStr = obj.toString;
10123
+ if (typeof toStr === "function") {
10124
+ try {
10125
+ const result = toStr.call(value);
10126
+ if (typeof result === "string" && result !== "[object Object]") return result;
10127
+ } catch {
10128
+ }
10129
+ }
10130
+ return "?";
10131
+ }
10132
+ return String(value);
10133
+ }
10346
10134
  async function traceClass(className, options) {
10347
10135
  const root = options?.root ?? process.cwd();
10348
10136
  const scanResult = await scanWorkspace(root, {
@@ -10376,53 +10164,16 @@ async function traceClass(className, options) {
10376
10164
  const { rules, classToRuleIds } = parseCssToIr(cssResult.code);
10377
10165
  const ruleIds = classToRuleIds.get(className);
10378
10166
  if (!ruleIds || ruleIds.length === 0) {
10379
- throw TwError.fromCompile("TRACE_NO_RULES_FOUND", `No rules found for class "${className}" after parsing CSS.`);
10167
+ throw TwError.fromCompile(
10168
+ "TRACE_NO_RULES_FOUND",
10169
+ `No rules found for class "${className}" after parsing CSS.`
10170
+ );
10380
10171
  }
10381
10172
  const resolver = new CascadeResolver();
10382
10173
  resolver.addRules(rules);
10383
10174
  resolver.registerClass(className, ruleIds);
10384
- const engineTraceResult = trace(className, resolver);
10385
- return convertTraceResult(engineTraceResult);
10386
- }
10387
- function safeToString(value) {
10388
- if (value === null || value === void 0) return "";
10389
- if (typeof value === "string") return String(value);
10390
- if (typeof value === "number") return String(value);
10391
- if (typeof value === "boolean") return String(value);
10392
- if (typeof value === "object" && value !== null) {
10393
- const obj = value;
10394
- const name = obj.name;
10395
- if (typeof name === "string" && name.length > 0) {
10396
- return name;
10397
- }
10398
- const objValue = obj.value;
10399
- if (objValue !== void 0) {
10400
- return String(objValue);
10401
- }
10402
- const objValueOf = obj.valueOf;
10403
- if (typeof objValueOf === "function") {
10404
- try {
10405
- const vo = objValueOf.call(value);
10406
- if (vo !== value) return String(vo);
10407
- } catch {
10408
- }
10409
- }
10410
- const toStr = obj.toString;
10411
- if (typeof toStr === "function") {
10412
- try {
10413
- const result = toStr.call(value);
10414
- if (typeof result === "string" && result !== "[object Object]") {
10415
- return result;
10416
- }
10417
- } catch {
10418
- }
10419
- }
10420
- return "?";
10421
- }
10422
- return String(value);
10423
- }
10424
- function convertTraceResult(engineResult) {
10425
- return {
10175
+ const engineResult = trace(className, resolver);
10176
+ const result = {
10426
10177
  class: safeToString(engineResult.class),
10427
10178
  definedAt: {
10428
10179
  file: safeToString(engineResult.definedAt.file),
@@ -10434,7 +10185,8 @@ function convertTraceResult(engineResult) {
10434
10185
  value: safeToString(v.value),
10435
10186
  source: {
10436
10187
  file: safeToString(v.source?.file ?? ""),
10437
- line: Number(v.source?.line ?? 0)
10188
+ line: Number(v.source?.line ?? 0),
10189
+ column: Number(v.source?.column ?? 0)
10438
10190
  }
10439
10191
  })),
10440
10192
  rules: engineResult.rules.map((r) => ({
@@ -10444,7 +10196,8 @@ function convertTraceResult(engineResult) {
10444
10196
  reason: r.reason ? safeToString(r.reason) : null,
10445
10197
  source: {
10446
10198
  file: safeToString(r.source?.file ?? ""),
10447
- line: Number(r.source?.line ?? 0)
10199
+ line: Number(r.source?.line ?? 0),
10200
+ column: Number(r.source?.column ?? 0)
10448
10201
  },
10449
10202
  specificity: Number(r.specificity ?? 0)
10450
10203
  })),
@@ -10453,17 +10206,18 @@ function convertTraceResult(engineResult) {
10453
10206
  winner: safeToString(c.winner),
10454
10207
  loser: safeToString(c.loser),
10455
10208
  stage: safeToString(c.stage),
10456
- causes: c.causes?.map(safeToString) ?? []
10209
+ causes: (c.causes ?? []).map(safeToString)
10457
10210
  })),
10458
10211
  finalStyle: engineResult.finalStyle.map((f) => ({
10459
10212
  property: safeToString(f.property),
10460
10213
  value: safeToString(f.value)
10461
10214
  }))
10462
10215
  };
10216
+ return result;
10463
10217
  }
10464
10218
  init_src2();
10465
10219
  function toRelativePath(root, value) {
10466
- const relative = path3.relative(root, value);
10220
+ const relative = path6__default.relative(root, value);
10467
10221
  return relative.length > 0 ? relative : ".";
10468
10222
  }
10469
10223
  function uniqueSorted(values) {
@@ -10532,7 +10286,7 @@ function tryCompileClasses(classes) {
10532
10286
  }
10533
10287
  }
10534
10288
  function traceSingleFile(filePath, root) {
10535
- const source = fs8.readFileSync(filePath, "utf8");
10289
+ const source = fs11__default.readFileSync(filePath, "utf8");
10536
10290
  const classes = uniqueSorted(scanSource(source));
10537
10291
  const imports = extractImports(source);
10538
10292
  const compiled = tryCompileClasses(classes);
@@ -10563,7 +10317,7 @@ function traceDirectory(targetDir, root) {
10563
10317
  const imports = [];
10564
10318
  const importKeys = /* @__PURE__ */ new Set();
10565
10319
  const files = scanResult.files.filter((entry) => isScannableFile(entry.file, DEFAULT_EXTENSIONS)).map((entry) => {
10566
- const source = fs8.readFileSync(entry.file, "utf8");
10320
+ const source = fs11__default.readFileSync(entry.file, "utf8");
10567
10321
  const fileImports = extractImports(source);
10568
10322
  for (const fileImport of fileImports) {
10569
10323
  const key = `${fileImport.kind}:${fileImport.source}`;
@@ -10594,12 +10348,12 @@ function traceDirectory(targetDir, root) {
10594
10348
  };
10595
10349
  }
10596
10350
  async function traceTarget(target, options = {}) {
10597
- const root = path3.resolve(options.root ?? process.cwd());
10598
- const resolvedTarget = path3.resolve(root, target);
10599
- if (!fs8.existsSync(resolvedTarget)) {
10351
+ const root = path6__default.resolve(options.root ?? process.cwd());
10352
+ const resolvedTarget = path6__default.resolve(root, target);
10353
+ if (!fs11__default.existsSync(resolvedTarget)) {
10600
10354
  throw new Error(`Trace target not found: ${resolvedTarget}`);
10601
10355
  }
10602
- const stat = fs8.statSync(resolvedTarget);
10356
+ const stat = fs11__default.statSync(resolvedTarget);
10603
10357
  if (stat.isDirectory()) {
10604
10358
  return traceDirectory(resolvedTarget, root);
10605
10359
  }
@@ -10768,7 +10522,7 @@ async function runGenerateTypesCli(rawArgs) {
10768
10522
  const logger = createCliLogger({ output });
10769
10523
  const cwd2 = process.cwd();
10770
10524
  const outFile = rawArgs.find((a) => a.startsWith("--out="))?.slice(6) ?? "src/types/tailwind-styled.d.ts";
10771
- const outPath = path3.resolve(cwd2, outFile);
10525
+ const outPath = path6__default.resolve(cwd2, outFile);
10772
10526
  output.writeText("");
10773
10527
  output.writeText(import_picocolors6.default.bold(import_picocolors6.default.cyan(" \u25C6 tw generate-types")));
10774
10528
  output.writeText(import_picocolors6.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
@@ -10782,12 +10536,11 @@ async function runGenerateTypesCli(rawArgs) {
10782
10536
  throw new Error("Native binding 'generateSubComponentTypes' tidak tersedia \u2014 pastikan build:rust sudah dijalankan");
10783
10537
  }
10784
10538
  result = binding.generateSubComponentTypes(cwd2, outPath);
10539
+ if (!result) throw new Error("generateSubComponentTypes mengembalikan null");
10785
10540
  spinner.stop(`Scanned ${result.filesScanned} files`);
10786
10541
  } catch (err) {
10787
10542
  spinner.error("Scan gagal");
10788
- logger.warn(err instanceof Error ? err.message : String(err));
10789
- output.writeText(import_picocolors6.default.dim(" \u2192 fallback ke JS scanner..."));
10790
- result = await fallbackJsScan(cwd2);
10543
+ throw err instanceof Error ? err : new Error(String(err));
10791
10544
  }
10792
10545
  if (!result) {
10793
10546
  logger.warn("Tidak ada hasil scan");
@@ -10805,12 +10558,12 @@ async function runGenerateTypesCli(rawArgs) {
10805
10558
  }
10806
10559
  output.writeText("");
10807
10560
  output.writeText(import_picocolors6.default.bold(" [2/2]") + import_picocolors6.default.cyan(" generate .d.ts"));
10808
- const outDir = path3.dirname(outPath);
10809
- if (!fs8.existsSync(outDir)) {
10810
- fs8.mkdirSync(outDir, { recursive: true });
10561
+ const outDir = path6__default.dirname(outPath);
10562
+ if (!fs11__default.existsSync(outDir)) {
10563
+ fs11__default.mkdirSync(outDir, { recursive: true });
10811
10564
  }
10812
- fs8.writeFileSync(outPath, result.dtsContent, "utf-8");
10813
- logger.ok(path3.relative(cwd2, outPath));
10565
+ fs11__default.writeFileSync(outPath, result.dtsContent, "utf-8");
10566
+ logger.ok(path6__default.relative(cwd2, outPath));
10814
10567
  output.writeText("");
10815
10568
  output.writeText(import_picocolors6.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
10816
10569
  output.writeText(import_picocolors6.default.bold(import_picocolors6.default.green(" \u2713 types generated")));
@@ -10821,11 +10574,11 @@ async function runGenerateTypesCli(rawArgs) {
10821
10574
  }
10822
10575
  async function loadNativeBinding2(cwd2) {
10823
10576
  const candidates = [
10824
- path3.join(cwd2, "native", "tailwind-styled-native.node"),
10825
- path3.join(cwd2, "node_modules", "tailwind-styled-v4", "native", "tailwind-styled-native.node")
10577
+ path6__default.join(cwd2, "native", "tailwind-styled-native.node"),
10578
+ path6__default.join(cwd2, "node_modules", "tailwind-styled-v4", "native", "tailwind-styled-native.node")
10826
10579
  ];
10827
10580
  for (const candidate of candidates) {
10828
- if (fs8.existsSync(candidate)) {
10581
+ if (fs11__default.existsSync(candidate)) {
10829
10582
  try {
10830
10583
  return __require(candidate);
10831
10584
  } catch {
@@ -10834,42 +10587,6 @@ async function loadNativeBinding2(cwd2) {
10834
10587
  }
10835
10588
  return null;
10836
10589
  }
10837
- async function fallbackJsScan(cwd2, outPath) {
10838
- const { execSync } = await import('child_process');
10839
- const registerRe = /registerSubComponent\s*\(\s*\{[^}]*name\s*:\s*["']([a-zA-Z][a-zA-Z0-9_-]*)["']/g;
10840
- const withSubRe = /\.withSub\s*<\s*([^>]+)\s*>/g;
10841
- const literalRe = /["']([a-zA-Z][a-zA-Z0-9_-]*)["']/g;
10842
- const names = /* @__PURE__ */ new Set();
10843
- let filesScanned = 0;
10844
- try {
10845
- const files = execSync(
10846
- `find . -name "*.tsx" -o -name "*.ts" -o -name "*.jsx" -o -name "*.js" | grep -v node_modules | grep -v .next | grep -v dist`,
10847
- { cwd: cwd2, encoding: "utf-8" }
10848
- ).trim().split("\n").filter(Boolean);
10849
- for (const file of files) {
10850
- try {
10851
- const source = fs8.readFileSync(path3.join(cwd2, file), "utf-8");
10852
- filesScanned++;
10853
- for (const m of source.matchAll(registerRe)) names.add(m[1]);
10854
- for (const m of source.matchAll(withSubRe)) {
10855
- for (const lit of m[1].matchAll(literalRe)) names.add(lit[1]);
10856
- }
10857
- } catch {
10858
- }
10859
- }
10860
- } catch {
10861
- }
10862
- const sorted = [...names].sort();
10863
- const union = sorted.map((n) => `"${n}"`).join(" | ") || "never";
10864
- const dtsContent = `// AUTO-GENERATED by tailwind-styled-v4 (JS fallback)
10865
- // DO NOT EDIT \u2014 Run: npx tw generate-types to regenerate
10866
-
10867
- declare module "tailwind-styled-v4" {
10868
- export type DetectedSubComponents = ${union}
10869
- }
10870
- `;
10871
- return { names: sorted, dtsContent, filesScanned };
10872
- }
10873
10590
 
10874
10591
  // packages/infrastructure/cli/src/commands/why.ts
10875
10592
  init_errors();
@@ -10920,7 +10637,7 @@ async function whyClass(className, options) {
10920
10637
  for (const file of scanResult.files) {
10921
10638
  const source = (() => {
10922
10639
  try {
10923
- return fs8.readFileSync(file.file, "utf8");
10640
+ return fs11__default.readFileSync(file.file, "utf8");
10924
10641
  } catch {
10925
10642
  return "";
10926
10643
  }
@@ -10934,7 +10651,7 @@ async function whyClass(className, options) {
10934
10651
  className
10935
10652
  ]);
10936
10653
  usedIn.push({
10937
- file: path3.relative(root, file.file) || path3.basename(file.file),
10654
+ file: path6__default.relative(root, file.file) || path6__default.basename(file.file),
10938
10655
  line: location.line,
10939
10656
  column: location.column,
10940
10657
  usage: normalizeScannedClass(fileClass)
@@ -11100,7 +10817,7 @@ function buildMainProgram(context) {
11100
10817
  new Map(miscCommands.map((command) => [command.name, command]));
11101
10818
  const scriptByName = new Map(scriptCommands.map((command) => [command.name, command]));
11102
10819
  const program2 = new Command("tw");
11103
- program2.name("tw").description("tailwind-styled-v4 CLI").option("--json", "Output strict JSON envelope").option("--debug", "Include stack traces for errors").option("--verbose", "Verbose runtime logs");
10820
+ program2.name("tw").description("tailwind-styled-v4 CLI").version("5.0.4", "--version", "Output the current version").option("--json", "Output strict JSON envelope").option("--debug", "Include stack traces for errors").option("--verbose", "Verbose runtime logs");
11104
10821
  program2.command("setup").description("Auto-setup project").option("--yes", "Skip prompts").option("--next", "Force Next.js").option("--vite", "Force Vite").option("--rspack", "Force Rspack").option("--react", "Force React").option("--dry-run", "Preview changes").option("--skip-install", "Skip package install").action(async (...actionArgs) => {
11105
10822
  const options = actionCommand(actionArgs).opts();
11106
10823
  const args = [];
@@ -11389,12 +11106,18 @@ function buildMainProgram(context) {
11389
11106
 
11390
11107
  // packages/infrastructure/cli/src/index.ts
11391
11108
  init_runtime();
11109
+ init_args();
11110
+ init_args();
11111
+ init_output();
11392
11112
  async function main2() {
11393
11113
  await runCliMain({
11394
11114
  importMetaUrl: import.meta.url,
11395
11115
  buildProgram: buildMainProgram
11396
11116
  });
11397
11117
  }
11398
- main2();
11118
+ var __filename2 = fileURLToPath(import.meta.url);
11119
+ if (process.argv[1] === __filename2) {
11120
+ main2();
11121
+ }
11399
11122
  //# sourceMappingURL=tw.mjs.map
11400
11123
  //# sourceMappingURL=tw.mjs.map