chaincss 2.0.7 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/CODE_OF_CONDUCT.md +21 -0
  3. package/CONTRIBUTING.md +28 -0
  4. package/README.md +455 -226
  5. package/demo/demo/node_modules/caniuse-db/fulldata-json/data-2.0.json +1 -0
  6. package/demo/index.html +16 -0
  7. package/demo/package.json +20 -0
  8. package/demo/src/App.tsx +117 -0
  9. package/demo/src/chaincss-barrel.ts +9 -0
  10. package/demo/src/main.tsx +8 -0
  11. package/demo/src/styles.chain.ts +300 -0
  12. package/demo/vite.config.ts +46 -0
  13. package/dist/cli/commands/build.d.ts +0 -1
  14. package/dist/cli/commands/cache.d.ts +1 -0
  15. package/dist/cli/commands/init.d.ts +6 -3
  16. package/dist/cli/commands/timeline.d.ts +0 -1
  17. package/dist/cli/commands/watch.d.ts +0 -1
  18. package/dist/cli/index.d.ts +0 -1
  19. package/dist/cli/index.js +3213 -5296
  20. package/dist/cli/types.d.ts +51 -20
  21. package/dist/cli/utils/config-loader.d.ts +0 -1
  22. package/dist/cli/utils/file-utils.d.ts +27 -3
  23. package/dist/cli/utils/logger.d.ts +0 -1
  24. package/dist/compiler/Chain.d.ts +215 -0
  25. package/dist/compiler/animations.d.ts +76 -0
  26. package/dist/compiler/atomic-optimizer.d.ts +47 -12
  27. package/dist/compiler/breakpoints.d.ts +46 -0
  28. package/dist/compiler/btt.d.ts +36 -60
  29. package/dist/compiler/cache-manager.d.ts +58 -4
  30. package/dist/compiler/commonProps.d.ts +0 -1
  31. package/dist/compiler/content-addressable-cache.d.ts +78 -0
  32. package/dist/compiler/helpers.d.ts +54 -0
  33. package/dist/compiler/index.d.ts +16 -9
  34. package/dist/compiler/index.js +4450 -4316
  35. package/dist/compiler/prefixer.d.ts +17 -1
  36. package/dist/compiler/shorthands.d.ts +28 -0
  37. package/dist/compiler/suggestions.d.ts +43 -0
  38. package/dist/compiler/theme-contract.d.ts +16 -27
  39. package/dist/compiler/token-resolver.d.ts +69 -0
  40. package/dist/compiler/tokens.d.ts +33 -8
  41. package/dist/core/auto-detector.d.ts +34 -0
  42. package/dist/core/common-utils.d.ts +97 -0
  43. package/dist/core/compiler.d.ts +63 -23
  44. package/dist/core/constants.d.ts +137 -36
  45. package/dist/core/smart-chain.d.ts +3 -0
  46. package/dist/core/types.d.ts +122 -15
  47. package/dist/core/utils.d.ts +134 -17
  48. package/dist/index.d.ts +52 -8
  49. package/dist/index.js +7090 -5578
  50. package/dist/plugins/vite.d.ts +7 -5
  51. package/dist/plugins/vite.js +2964 -25641
  52. package/dist/plugins/webpack.d.ts +24 -1
  53. package/dist/plugins/webpack.js +209 -72
  54. package/dist/runtime/Chain.d.ts +32 -0
  55. package/dist/runtime/auto-hooks.d.ts +11 -0
  56. package/dist/runtime/hmr.d.ts +22 -2
  57. package/dist/runtime/index.d.ts +3 -2
  58. package/dist/runtime/index.js +3648 -301
  59. package/dist/runtime/injector.d.ts +39 -72
  60. package/dist/runtime/react.d.ts +17 -12
  61. package/dist/runtime/svelte.d.ts +15 -0
  62. package/dist/runtime/types.d.ts +126 -4
  63. package/dist/runtime/utils.d.ts +0 -1
  64. package/dist/runtime/vue.d.ts +34 -14
  65. package/package.json +59 -66
  66. package/src/cli/commands/build.ts +133 -0
  67. package/src/cli/commands/cache.ts +371 -0
  68. package/src/cli/commands/init.ts +230 -0
  69. package/src/cli/commands/timeline.ts +435 -0
  70. package/src/cli/commands/watch.ts +211 -0
  71. package/src/cli/index.ts +226 -0
  72. package/src/cli/types.ts +100 -0
  73. package/src/cli/utils/config-loader.ts +174 -0
  74. package/src/cli/utils/file-utils.ts +139 -0
  75. package/src/cli/utils/logger.ts +74 -0
  76. package/src/compiler/Chain.ts +831 -0
  77. package/src/compiler/animations.ts +517 -0
  78. package/src/compiler/atomic-optimizer.ts +786 -0
  79. package/src/compiler/breakpoints.ts +347 -0
  80. package/src/compiler/btt.ts +1147 -0
  81. package/src/compiler/cache-manager.ts +446 -0
  82. package/src/compiler/commonProps.ts +18 -0
  83. package/src/compiler/content-addressable-cache.ts +478 -0
  84. package/src/compiler/helpers.ts +407 -0
  85. package/src/compiler/index.ts +72 -0
  86. package/src/compiler/prefixer.ts +724 -0
  87. package/src/compiler/shorthands.ts +558 -0
  88. package/src/compiler/suggestions.ts +436 -0
  89. package/src/compiler/theme-contract.ts +197 -0
  90. package/src/compiler/token-resolver.ts +241 -0
  91. package/src/compiler/tokens.ts +612 -0
  92. package/src/core/auto-detector.ts +187 -0
  93. package/src/core/common-utils.ts +423 -0
  94. package/src/core/compiler.ts +835 -0
  95. package/src/core/constants.ts +424 -0
  96. package/src/core/index.ts +107 -0
  97. package/src/core/smart-chain.ts +163 -0
  98. package/src/core/types.ts +257 -0
  99. package/src/core/utils.ts +598 -0
  100. package/src/index.ts +208 -0
  101. package/src/plugins/vite.d.ts +316 -0
  102. package/src/plugins/vite.ts +424 -0
  103. package/src/plugins/webpack.d.ts +289 -0
  104. package/src/plugins/webpack.ts +416 -0
  105. package/src/runtime/Chain.ts +242 -0
  106. package/src/runtime/auto-hooks.tsx +127 -0
  107. package/src/runtime/auto-vue.ts +72 -0
  108. package/src/runtime/hmr.ts +212 -0
  109. package/src/runtime/index.ts +82 -0
  110. package/src/runtime/injector.ts +273 -0
  111. package/src/runtime/react.tsx +269 -0
  112. package/src/runtime/svelte.ts +15 -0
  113. package/src/runtime/types.ts +256 -0
  114. package/src/runtime/utils.ts +128 -0
  115. package/src/runtime/vite-env.d.ts +120 -0
  116. package/src/runtime/vue.ts +231 -0
  117. package/tsconfig.build.json +41 -0
  118. package/tsconfig.json +25 -0
  119. package/tsconfig.runtimes.json +18 -0
  120. package/dist/cli/cli.cjs +0 -7
  121. package/dist/cli/commands/build.d.ts.map +0 -1
  122. package/dist/cli/commands/compile.d.ts +0 -3
  123. package/dist/cli/commands/compile.d.ts.map +0 -1
  124. package/dist/cli/commands/init.d.ts.map +0 -1
  125. package/dist/cli/commands/timeline.d.ts.map +0 -1
  126. package/dist/cli/commands/watch.d.ts.map +0 -1
  127. package/dist/cli/index.d.ts.map +0 -1
  128. package/dist/cli/types.d.ts.map +0 -1
  129. package/dist/cli/utils/config-loader.d.ts.map +0 -1
  130. package/dist/cli/utils/file-utils.d.ts.map +0 -1
  131. package/dist/cli/utils/logger.d.ts.map +0 -1
  132. package/dist/compiler/atomic-optimizer.d.ts.map +0 -1
  133. package/dist/compiler/btt.d.ts.map +0 -1
  134. package/dist/compiler/cache-manager.d.ts.map +0 -1
  135. package/dist/compiler/commonProps.d.ts.map +0 -1
  136. package/dist/compiler/index.d.ts.map +0 -1
  137. package/dist/compiler/prefixer.d.ts.map +0 -1
  138. package/dist/compiler/theme-contract.d.ts.map +0 -1
  139. package/dist/compiler/tokens.d.ts.map +0 -1
  140. package/dist/compiler/types.d.ts +0 -57
  141. package/dist/compiler/types.d.ts.map +0 -1
  142. package/dist/core/compiler.d.ts.map +0 -1
  143. package/dist/core/constants.d.ts.map +0 -1
  144. package/dist/core/index.d.ts +0 -4
  145. package/dist/core/index.d.ts.map +0 -1
  146. package/dist/core/types.d.ts.map +0 -1
  147. package/dist/core/utils.d.ts.map +0 -1
  148. package/dist/index.d.ts.map +0 -1
  149. package/dist/plugins/vite.d.ts.map +0 -1
  150. package/dist/plugins/webpack.d.ts.map +0 -1
  151. package/dist/runtime/hmr.d.ts.map +0 -1
  152. package/dist/runtime/index.d.ts.map +0 -1
  153. package/dist/runtime/injector.d.ts.map +0 -1
  154. package/dist/runtime/react.d.ts.map +0 -1
  155. package/dist/runtime/react.js +0 -324
  156. package/dist/runtime/types.d.ts.map +0 -1
  157. package/dist/runtime/utils.d.ts.map +0 -1
  158. package/dist/runtime/vue.d.ts.map +0 -1
  159. package/dist/runtime/vue.js +0 -286
@@ -0,0 +1,598 @@
1
+ // chaincss/src/core/utils.ts
2
+
3
+ import crypto from 'node:crypto';
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+
7
+ /**
8
+ * 1. RE-EXPORTS
9
+ * Re-exporting everything from common-utils ensures the Compiler
10
+ * can still find processStyleObject, resolveToken, and kebabCase
11
+ * without changing its import statements.
12
+ */
13
+ export * from './common-utils.js';
14
+
15
+ // Import types
16
+ import type { StyleDefinition } from '../compiler/btt.js';
17
+
18
+ /**
19
+ * 2. HASHING & NAMING (Node/Compiler Only)
20
+ */
21
+ export function hashString(str: string, length: number = 6): string {
22
+ return crypto.createHash('sha1').update(str).digest('hex').slice(0, length);
23
+ }
24
+
25
+ export function generateClassName(styleId: string, naming: 'hash' | 'readable' = 'hash'): string {
26
+ if (naming === 'hash') {
27
+ return `c_${hashString(styleId)}`;
28
+ }
29
+ // Clean the styleId for readable names
30
+ const cleanId = styleId
31
+ .replace(/[^a-zA-Z0-9]/g, '-')
32
+ .replace(/-+/g, '-')
33
+ .replace(/^-|-$/g, '')
34
+ .toLowerCase();
35
+ return `chain-${cleanId}`;
36
+ }
37
+
38
+ // Generate atomic class name
39
+ export function generateAtomicClassName(prop: string, value: string, type: 'atomic' | 'utility' = 'atomic'): string {
40
+ const hash = hashString(`${prop}:${value}`, 6);
41
+ const propKebab = kebabCase(prop);
42
+
43
+ if (type === 'utility') {
44
+ return `u-${propKebab}-${hash}`;
45
+ }
46
+ return `a-${propKebab}-${hash}`;
47
+ }
48
+
49
+ // Generate component class name with hash for uniqueness
50
+ export function generateComponentClassName(componentName: string, hash?: string): string {
51
+ const cleanName = componentName
52
+ .replace(/[^a-zA-Z0-9]/g, '-')
53
+ .replace(/-+/g, '-')
54
+ .replace(/^-|-$/g, '')
55
+ .toLowerCase();
56
+
57
+ const suffix = hash || hashString(componentName, 4);
58
+ return `c-${cleanName}-${suffix}`;
59
+ }
60
+
61
+ /**
62
+ * 3. OBJECT MANIPULATION
63
+ */
64
+ export function deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {
65
+ const result = { ...target } as any;
66
+
67
+ for (const key in source) {
68
+ const srcVal = source[key];
69
+ const targetVal = result[key];
70
+
71
+ if (srcVal && typeof srcVal === 'object' && !Array.isArray(srcVal)) {
72
+ result[key] = deepMerge(targetVal || {}, srcVal);
73
+ } else if (srcVal !== undefined) {
74
+ result[key] = srcVal;
75
+ }
76
+ }
77
+
78
+ return result;
79
+ }
80
+
81
+ // Deep clone an object
82
+ export function deepClone<T>(obj: T): T {
83
+ if (obj === null || typeof obj !== 'object') return obj;
84
+ if (Array.isArray(obj)) return obj.map(item => deepClone(item)) as any;
85
+
86
+ const cloned: any = {};
87
+ for (const key in obj) {
88
+ if (obj.hasOwnProperty(key)) {
89
+ cloned[key] = deepClone(obj[key]);
90
+ }
91
+ }
92
+ return cloned;
93
+ }
94
+
95
+ // Check if two objects are deeply equal
96
+ export function deepEqual(obj1: any, obj2: any): boolean {
97
+ if (obj1 === obj2) return true;
98
+ if (typeof obj1 !== 'object' || typeof obj2 !== 'object') return false;
99
+ if (obj1 === null || obj2 === null) return false;
100
+
101
+ const keys1 = Object.keys(obj1);
102
+ const keys2 = Object.keys(obj2);
103
+
104
+ if (keys1.length !== keys2.length) return false;
105
+
106
+ for (const key of keys1) {
107
+ if (!keys2.includes(key)) return false;
108
+ if (!deepEqual(obj1[key], obj2[key])) return false;
109
+ }
110
+
111
+ return true;
112
+ }
113
+
114
+ // Pick specific keys from an object
115
+ export function pick<T extends Record<string, any>, K extends keyof T>(
116
+ obj: T,
117
+ keys: K[]
118
+ ): Pick<T, K> {
119
+ const result: Partial<T> = {};
120
+ for (const key of keys) {
121
+ if (key in obj) {
122
+ result[key] = obj[key];
123
+ }
124
+ }
125
+ return result as Pick<T, K>;
126
+ }
127
+
128
+ // Omit specific keys from an object
129
+ export function omit<T extends Record<string, any>, K extends keyof T>(
130
+ obj: T,
131
+ keys: K[]
132
+ ): Omit<T, K> {
133
+ const result = { ...obj };
134
+ for (const key of keys) {
135
+ delete result[key];
136
+ }
137
+ return result;
138
+ }
139
+
140
+ /**
141
+ * 4. FILE SYSTEM UTILS (Node Only)
142
+ */
143
+ export function ensureDir(dir: string): void {
144
+ if (!fs.existsSync(dir)) {
145
+ fs.mkdirSync(dir, { recursive: true });
146
+ }
147
+ }
148
+
149
+ export function writeFile(filePath: string, content: string): void {
150
+ const dir = path.dirname(filePath);
151
+ ensureDir(dir);
152
+ fs.writeFileSync(filePath, content, 'utf8');
153
+ }
154
+
155
+ export function readFile(filePath: string): string {
156
+ if (!fs.existsSync(filePath)) {
157
+ throw new Error(`File not found: ${filePath}`);
158
+ }
159
+ return fs.readFileSync(filePath, 'utf8');
160
+ }
161
+
162
+ export function fileExists(filePath: string): boolean {
163
+ return fs.existsSync(filePath);
164
+ }
165
+
166
+ export function getFileExtension(filePath: string): string {
167
+ return path.extname(filePath);
168
+ }
169
+
170
+ export function getBaseName(filePath: string): string {
171
+ return path.basename(filePath, path.extname(filePath));
172
+ }
173
+
174
+ export function getDirName(filePath: string): string {
175
+ return path.dirname(filePath);
176
+ }
177
+
178
+ // Resolve a relative path from current working directory
179
+ export function resolvePath(filePath: string): string {
180
+ return path.resolve(process.cwd(), filePath);
181
+ }
182
+
183
+ // Check if a path is a directory
184
+ export function isDirectory(filePath: string): boolean {
185
+ try {
186
+ return fs.statSync(filePath).isDirectory();
187
+ } catch {
188
+ return false;
189
+ }
190
+ }
191
+
192
+ // Get all files recursively in a directory
193
+ export function getAllFiles(dir: string, pattern?: RegExp): string[] {
194
+ const files: string[] = [];
195
+
196
+ const readDir = (currentDir: string) => {
197
+ const entries = fs.readdirSync(currentDir);
198
+
199
+ for (const entry of entries) {
200
+ const fullPath = path.join(currentDir, entry);
201
+ const stat = fs.statSync(fullPath);
202
+
203
+ if (stat.isDirectory()) {
204
+ readDir(fullPath);
205
+ } else if (!pattern || pattern.test(fullPath)) {
206
+ files.push(fullPath);
207
+ }
208
+ }
209
+ };
210
+
211
+ readDir(dir);
212
+ return files;
213
+ }
214
+
215
+ /**
216
+ * 5. FORMATTING
217
+ */
218
+ export function formatCSS(css: string, minify: boolean = false): string {
219
+ if (!css || css.trim().length === 0) return '';
220
+
221
+ if (!minify) {
222
+ // Format nicely with proper indentation
223
+ let formatted = css
224
+ .replace(/\s*{\s*/g, ' {\n ')
225
+ .replace(/;\s*/g, ';\n ')
226
+ .replace(/\s*}\s*/g, '\n}\n')
227
+ .replace(/\n\s*\n/g, '\n');
228
+
229
+ // Ensure proper spacing for media queries
230
+ formatted = formatted.replace(/@media[^{]+\{/g, match => {
231
+ return match.replace(/\{/, ' {\n');
232
+ });
233
+
234
+ return formatted.trim();
235
+ }
236
+
237
+ // Minify CSS
238
+ return css
239
+ .replace(/\/\*.*?\*\//g, '') // Remove comments
240
+ .replace(/\s+/g, ' ') // Collapse whitespace
241
+ .replace(/\s*{\s*/g, '{') // Remove spaces around braces
242
+ .replace(/\s*}\s*/g, '}') // Remove spaces around braces
243
+ .replace(/\s*;\s*/g, ';') // Remove spaces around semicolons
244
+ .replace(/\s*:\s*/g, ':') // Remove spaces around colons
245
+ .replace(/;}/g, '}') // Remove last semicolon
246
+ .trim();
247
+ }
248
+
249
+ // Format JavaScript/TypeScript code
250
+ export function formatJS(code: string, minify: boolean = false): string {
251
+ if (!minify) {
252
+ return code;
253
+ }
254
+
255
+ return code
256
+ .replace(/\/\/.*$/gm, '') // Remove single-line comments
257
+ .replace(/\/\*.*?\*\//g, '') // Remove multi-line comments
258
+ .replace(/\s+/g, ' ') // Collapse whitespace
259
+ .trim();
260
+ }
261
+
262
+ // Convert string to kebab-case
263
+ export function kebabCase(str: string): string {
264
+ return str
265
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
266
+ .replace(/[\s_]+/g, '-')
267
+ .toLowerCase();
268
+ }
269
+
270
+ // Convert string to camelCase
271
+ export function camelCase(str: string): string {
272
+ return str
273
+ .replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : '')
274
+ .replace(/^[A-Z]/, char => char.toLowerCase());
275
+ }
276
+
277
+ // Convert string to PascalCase
278
+ export function pascalCase(str: string): string {
279
+ const camel = camelCase(str);
280
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
281
+ }
282
+
283
+ // Convert string to snake_case
284
+ export function snakeCase(str: string): string {
285
+ return str
286
+ .replace(/([a-z])([A-Z])/g, '$1_$2')
287
+ .replace(/[\s-]+/g, '_')
288
+ .toLowerCase();
289
+ }
290
+
291
+ /**
292
+ * 6. STRING UTILITIES
293
+ */
294
+ export function truncate(str: string, length: number, suffix: string = '...'): string {
295
+ if (str.length <= length) return str;
296
+ return str.slice(0, length - suffix.length) + suffix;
297
+ }
298
+
299
+ export function indent(str: string, level: number = 1, char: string = ' '): string {
300
+ const indentStr = char.repeat(level);
301
+ return str
302
+ .split('\n')
303
+ .map(line => indentStr + line)
304
+ .join('\n');
305
+ }
306
+
307
+ export function stripIndent(str: string): string {
308
+ const lines = str.split('\n');
309
+ const minIndent = Math.min(
310
+ ...lines
311
+ .filter(line => line.trim())
312
+ .map(line => line.match(/^\s*/)?.[0].length || 0)
313
+ );
314
+
315
+ return lines
316
+ .map(line => line.slice(minIndent))
317
+ .join('\n')
318
+ .trim();
319
+ }
320
+
321
+ /**
322
+ * 7. ARRAY UTILITIES
323
+ */
324
+ export function unique<T>(arr: T[], key?: keyof T): T[] {
325
+ if (!key) {
326
+ return [...new Set(arr)];
327
+ }
328
+
329
+ const seen = new Set();
330
+ return arr.filter(item => {
331
+ const value = item[key];
332
+ if (seen.has(value)) return false;
333
+ seen.add(value);
334
+ return true;
335
+ });
336
+ }
337
+
338
+ export function chunk<T>(arr: T[], size: number): T[][] {
339
+ const result: T[][] = [];
340
+ for (let i = 0; i < arr.length; i += size) {
341
+ result.push(arr.slice(i, i + size));
342
+ }
343
+ return result;
344
+ }
345
+
346
+ export function groupBy<T>(arr: T[], key: keyof T): Record<string, T[]> {
347
+ const result: Record<string, T[]> = {};
348
+
349
+ for (const item of arr) {
350
+ const groupKey = String(item[key]);
351
+ if (!result[groupKey]) {
352
+ result[groupKey] = [];
353
+ }
354
+ result[groupKey].push(item);
355
+ }
356
+
357
+ return result;
358
+ }
359
+
360
+ /**
361
+ * 8. PERFORMANCE UTILITIES
362
+ */
363
+ export function debounce<T extends (...args: any[]) => any>(
364
+ fn: T,
365
+ delay: number
366
+ ): (...args: Parameters<T>) => void {
367
+ let timeout: NodeJS.Timeout | null = null;
368
+
369
+ return (...args: Parameters<T>) => {
370
+ if (timeout) clearTimeout(timeout);
371
+ timeout = setTimeout(() => fn(...args), delay);
372
+ };
373
+ }
374
+
375
+ export function throttle<T extends (...args: any[]) => any>(
376
+ fn: T,
377
+ limit: number
378
+ ): (...args: Parameters<T>) => void {
379
+ let inThrottle = false;
380
+
381
+ return (...args: Parameters<T>) => {
382
+ if (!inThrottle) {
383
+ fn(...args);
384
+ inThrottle = true;
385
+ setTimeout(() => (inThrottle = false), limit);
386
+ }
387
+ };
388
+ }
389
+
390
+ /**
391
+ * 9. ERROR HANDLING
392
+ */
393
+ export class ChainCSSError extends Error {
394
+ public code: string;
395
+ public details?: any;
396
+
397
+ constructor(message: string, code: string = 'CHAINCSS_ERROR', details?: any) {
398
+ super(message);
399
+ this.name = 'ChainCSSError';
400
+ this.code = code;
401
+ this.details = details;
402
+ }
403
+ }
404
+
405
+ export function tryOrWarn<T>(fn: () => T, defaultValue: T, message?: string): T {
406
+ try {
407
+ return fn();
408
+ } catch (error) {
409
+ if (message) {
410
+ console.warn(message, error);
411
+ }
412
+ return defaultValue;
413
+ }
414
+ }
415
+
416
+ export function tryOrThrow<T>(fn: () => T, errorMessage?: string): T {
417
+ try {
418
+ return fn();
419
+ } catch (error) {
420
+ throw new ChainCSSError(
421
+ errorMessage || (error as Error).message,
422
+ 'EXECUTION_ERROR',
423
+ error
424
+ );
425
+ }
426
+ }
427
+
428
+ /**
429
+ * 10. LOGGING UTILITIES (Node Only)
430
+ */
431
+ const LOG_LEVELS = {
432
+ debug: 0,
433
+ info: 1,
434
+ warn: 2,
435
+ error: 3,
436
+ silent: 4
437
+ };
438
+
439
+ let currentLogLevel = process.env.DEBUG ? 'debug' : 'info';
440
+
441
+ export function setLogLevel(level: keyof typeof LOG_LEVELS): void {
442
+ currentLogLevel = level;
443
+ }
444
+
445
+ function shouldLog(level: keyof typeof LOG_LEVELS): boolean {
446
+ return LOG_LEVELS[level as keyof typeof LOG_LEVELS] >= LOG_LEVELS[currentLogLevel as keyof typeof LOG_LEVELS];
447
+ }
448
+
449
+ export function logDebug(message: string, ...args: any[]): void {
450
+ if (shouldLog('debug')) {
451
+ console.debug(`[ChainCSS Debug] ${message}`, ...args);
452
+ }
453
+ }
454
+
455
+ export function logInfo(message: string, ...args: any[]): void {
456
+ if (shouldLog('info')) {
457
+ console.log(`[ChainCSS] ${message}`, ...args);
458
+ }
459
+ }
460
+
461
+ export function logWarn(message: string, ...args: any[]): void {
462
+ if (shouldLog('warn')) {
463
+ console.warn(`[ChainCSS Warning] ${message}`, ...args);
464
+ }
465
+ }
466
+
467
+ export function logError(message: string, ...args: any[]): void {
468
+ if (shouldLog('error')) {
469
+ console.error(`[ChainCSS Error] ${message}`, ...args);
470
+ }
471
+ }
472
+
473
+ /**
474
+ * 11. MEMORY MANAGEMENT
475
+ */
476
+ export function getMemoryUsage(): { rss: number; heapTotal: number; heapUsed: number; external: number } {
477
+ const usage = process.memoryUsage();
478
+ return {
479
+ rss: usage.rss,
480
+ heapTotal: usage.heapTotal,
481
+ heapUsed: usage.heapUsed,
482
+ external: usage.external
483
+ };
484
+ }
485
+
486
+ export function formatBytes(bytes: number): string {
487
+ if (bytes === 0) return '0 Bytes';
488
+
489
+ const k = 1024;
490
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
491
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
492
+
493
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
494
+ }
495
+
496
+ /**
497
+ * 12. VALIDATION UTILITIES
498
+ */
499
+ export function isValidSelector(selector: string): boolean {
500
+ // Basic selector validation
501
+ if (!selector || typeof selector !== 'string') return false;
502
+ if (selector.length > 100) return false;
503
+
504
+ // Check for invalid characters
505
+ const invalidChars = /[<>`~]/;
506
+ if (invalidChars.test(selector)) return false;
507
+
508
+ return true;
509
+ }
510
+
511
+ export function isValidClassName(className: string): boolean {
512
+ if (!className || typeof className !== 'string') return false;
513
+ if (className.length > 50) return false;
514
+
515
+ // CSS class name regex (letters, numbers, hyphens, underscores)
516
+ const classNameRegex = /^[a-zA-Z_][a-zA-Z0-9_-]*$/;
517
+ return classNameRegex.test(className);
518
+ }
519
+
520
+ export function isValidCSSProperty(prop: string): boolean {
521
+ if (!prop || typeof prop !== 'string') return false;
522
+ // CSS property regex
523
+ const cssPropRegex = /^[a-z][a-z-]*$/;
524
+ return cssPropRegex.test(prop);
525
+ }
526
+
527
+ /**
528
+ * 13. EXPORTS
529
+ */
530
+ export default {
531
+ // Hashing
532
+ hashString,
533
+ generateClassName,
534
+ generateAtomicClassName,
535
+ generateComponentClassName,
536
+
537
+ // Objects
538
+ deepMerge,
539
+ deepClone,
540
+ deepEqual,
541
+ pick,
542
+ omit,
543
+
544
+ // Filesystem
545
+ ensureDir,
546
+ writeFile,
547
+ readFile,
548
+ fileExists,
549
+ getFileExtension,
550
+ getBaseName,
551
+ getDirName,
552
+ resolvePath,
553
+ isDirectory,
554
+ getAllFiles,
555
+
556
+ // Formatting
557
+ formatCSS,
558
+ formatJS,
559
+ kebabCase,
560
+ camelCase,
561
+ pascalCase,
562
+ snakeCase,
563
+
564
+ // Strings
565
+ truncate,
566
+ indent,
567
+ stripIndent,
568
+
569
+ // Arrays
570
+ unique,
571
+ chunk,
572
+ groupBy,
573
+
574
+ // Performance
575
+ debounce,
576
+ throttle,
577
+
578
+ // Errors
579
+ ChainCSSError,
580
+ tryOrWarn,
581
+ tryOrThrow,
582
+
583
+ // Logging
584
+ setLogLevel,
585
+ logDebug,
586
+ logInfo,
587
+ logWarn,
588
+ logError,
589
+
590
+ // Memory
591
+ getMemoryUsage,
592
+ formatBytes,
593
+
594
+ // Validation
595
+ isValidSelector,
596
+ isValidClassName,
597
+ isValidCSSProperty
598
+ };