@bloomneo/appkit 1.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +902 -0
- package/bin/appkit.js +71 -0
- package/bin/commands/generate.js +1050 -0
- package/bin/templates/backend/README.md.template +39 -0
- package/bin/templates/backend/api.http.template +0 -0
- package/bin/templates/backend/docs/APPKIT_CLI.md +507 -0
- package/bin/templates/backend/docs/APPKIT_COMMENTS_GUIDELINES.md +61 -0
- package/bin/templates/backend/docs/APPKIT_LLM_GUIDE.md +2539 -0
- package/bin/templates/backend/package.json.template +34 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.http.template +29 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.route.ts.template +36 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.service.ts.template +88 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.types.ts.template +18 -0
- package/bin/templates/backend/src/api/lib/api-router.ts.template +84 -0
- package/bin/templates/backend/src/api/server.ts.template +188 -0
- package/bin/templates/backend/tsconfig.api.json.template +24 -0
- package/bin/templates/backend/tsconfig.json.template +40 -0
- package/bin/templates/feature/feature.http.template +63 -0
- package/bin/templates/feature/feature.route.ts.template +36 -0
- package/bin/templates/feature/feature.service.ts.template +81 -0
- package/bin/templates/feature/feature.types.ts.template +23 -0
- package/bin/templates/feature-db/feature.http.template +63 -0
- package/bin/templates/feature-db/feature.model.ts.template +74 -0
- package/bin/templates/feature-db/feature.route.ts.template +58 -0
- package/bin/templates/feature-db/feature.service.ts.template +231 -0
- package/bin/templates/feature-db/feature.types.ts.template +25 -0
- package/bin/templates/feature-db/schema-addition.prisma.template +9 -0
- package/bin/templates/feature-db/seeding/README.md.template +57 -0
- package/bin/templates/feature-db/seeding/feature.seed.js.template +67 -0
- package/bin/templates/feature-user/schema-addition.prisma.template +19 -0
- package/bin/templates/feature-user/user.http.template +157 -0
- package/bin/templates/feature-user/user.model.ts.template +244 -0
- package/bin/templates/feature-user/user.route.ts.template +379 -0
- package/bin/templates/feature-user/user.seed.js.template +182 -0
- package/bin/templates/feature-user/user.service.ts.template +426 -0
- package/bin/templates/feature-user/user.types.ts.template +127 -0
- package/dist/auth/auth.d.ts +182 -0
- package/dist/auth/auth.d.ts.map +1 -0
- package/dist/auth/auth.js +477 -0
- package/dist/auth/auth.js.map +1 -0
- package/dist/auth/defaults.d.ts +104 -0
- package/dist/auth/defaults.d.ts.map +1 -0
- package/dist/auth/defaults.js +374 -0
- package/dist/auth/defaults.js.map +1 -0
- package/dist/auth/index.d.ts +70 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +94 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/cache/cache.d.ts +118 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +249 -0
- package/dist/cache/cache.js.map +1 -0
- package/dist/cache/defaults.d.ts +63 -0
- package/dist/cache/defaults.d.ts.map +1 -0
- package/dist/cache/defaults.js +193 -0
- package/dist/cache/defaults.js.map +1 -0
- package/dist/cache/index.d.ts +101 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +203 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/strategies/memory.d.ts +138 -0
- package/dist/cache/strategies/memory.d.ts.map +1 -0
- package/dist/cache/strategies/memory.js +348 -0
- package/dist/cache/strategies/memory.js.map +1 -0
- package/dist/cache/strategies/redis.d.ts +105 -0
- package/dist/cache/strategies/redis.d.ts.map +1 -0
- package/dist/cache/strategies/redis.js +318 -0
- package/dist/cache/strategies/redis.js.map +1 -0
- package/dist/config/config.d.ts +62 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +107 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/defaults.d.ts +44 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +217 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +105 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +163 -0
- package/dist/config/index.js.map +1 -0
- package/dist/database/adapters/mongoose.d.ts +106 -0
- package/dist/database/adapters/mongoose.d.ts.map +1 -0
- package/dist/database/adapters/mongoose.js +480 -0
- package/dist/database/adapters/mongoose.js.map +1 -0
- package/dist/database/adapters/prisma.d.ts +106 -0
- package/dist/database/adapters/prisma.d.ts.map +1 -0
- package/dist/database/adapters/prisma.js +494 -0
- package/dist/database/adapters/prisma.js.map +1 -0
- package/dist/database/defaults.d.ts +87 -0
- package/dist/database/defaults.d.ts.map +1 -0
- package/dist/database/defaults.js +271 -0
- package/dist/database/defaults.js.map +1 -0
- package/dist/database/index.d.ts +137 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +490 -0
- package/dist/database/index.js.map +1 -0
- package/dist/email/defaults.d.ts +100 -0
- package/dist/email/defaults.d.ts.map +1 -0
- package/dist/email/defaults.js +400 -0
- package/dist/email/defaults.js.map +1 -0
- package/dist/email/email.d.ts +139 -0
- package/dist/email/email.d.ts.map +1 -0
- package/dist/email/email.js +316 -0
- package/dist/email/email.js.map +1 -0
- package/dist/email/index.d.ts +176 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +251 -0
- package/dist/email/index.js.map +1 -0
- package/dist/email/strategies/console.d.ts +90 -0
- package/dist/email/strategies/console.d.ts.map +1 -0
- package/dist/email/strategies/console.js +268 -0
- package/dist/email/strategies/console.js.map +1 -0
- package/dist/email/strategies/resend.d.ts +84 -0
- package/dist/email/strategies/resend.d.ts.map +1 -0
- package/dist/email/strategies/resend.js +266 -0
- package/dist/email/strategies/resend.js.map +1 -0
- package/dist/email/strategies/smtp.d.ts +77 -0
- package/dist/email/strategies/smtp.d.ts.map +1 -0
- package/dist/email/strategies/smtp.js +286 -0
- package/dist/email/strategies/smtp.js.map +1 -0
- package/dist/error/defaults.d.ts +40 -0
- package/dist/error/defaults.d.ts.map +1 -0
- package/dist/error/defaults.js +75 -0
- package/dist/error/defaults.js.map +1 -0
- package/dist/error/error.d.ts +140 -0
- package/dist/error/error.d.ts.map +1 -0
- package/dist/error/error.js +200 -0
- package/dist/error/error.js.map +1 -0
- package/dist/error/index.d.ts +145 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/index.js +145 -0
- package/dist/error/index.js.map +1 -0
- package/dist/event/defaults.d.ts +111 -0
- package/dist/event/defaults.d.ts.map +1 -0
- package/dist/event/defaults.js +378 -0
- package/dist/event/defaults.js.map +1 -0
- package/dist/event/event.d.ts +171 -0
- package/dist/event/event.d.ts.map +1 -0
- package/dist/event/event.js +391 -0
- package/dist/event/event.js.map +1 -0
- package/dist/event/index.d.ts +173 -0
- package/dist/event/index.d.ts.map +1 -0
- package/dist/event/index.js +302 -0
- package/dist/event/index.js.map +1 -0
- package/dist/event/strategies/memory.d.ts +122 -0
- package/dist/event/strategies/memory.d.ts.map +1 -0
- package/dist/event/strategies/memory.js +331 -0
- package/dist/event/strategies/memory.js.map +1 -0
- package/dist/event/strategies/redis.d.ts +115 -0
- package/dist/event/strategies/redis.d.ts.map +1 -0
- package/dist/event/strategies/redis.js +434 -0
- package/dist/event/strategies/redis.js.map +1 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/logger/defaults.d.ts +67 -0
- package/dist/logger/defaults.d.ts.map +1 -0
- package/dist/logger/defaults.js +213 -0
- package/dist/logger/defaults.js.map +1 -0
- package/dist/logger/index.d.ts +84 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +101 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/logger.d.ts +165 -0
- package/dist/logger/logger.d.ts.map +1 -0
- package/dist/logger/logger.js +843 -0
- package/dist/logger/logger.js.map +1 -0
- package/dist/logger/transports/console.d.ts +102 -0
- package/dist/logger/transports/console.d.ts.map +1 -0
- package/dist/logger/transports/console.js +276 -0
- package/dist/logger/transports/console.js.map +1 -0
- package/dist/logger/transports/database.d.ts +153 -0
- package/dist/logger/transports/database.d.ts.map +1 -0
- package/dist/logger/transports/database.js +539 -0
- package/dist/logger/transports/database.js.map +1 -0
- package/dist/logger/transports/file.d.ts +146 -0
- package/dist/logger/transports/file.d.ts.map +1 -0
- package/dist/logger/transports/file.js +464 -0
- package/dist/logger/transports/file.js.map +1 -0
- package/dist/logger/transports/http.d.ts +128 -0
- package/dist/logger/transports/http.d.ts.map +1 -0
- package/dist/logger/transports/http.js +401 -0
- package/dist/logger/transports/http.js.map +1 -0
- package/dist/logger/transports/webhook.d.ts +152 -0
- package/dist/logger/transports/webhook.d.ts.map +1 -0
- package/dist/logger/transports/webhook.js +485 -0
- package/dist/logger/transports/webhook.js.map +1 -0
- package/dist/queue/defaults.d.ts +66 -0
- package/dist/queue/defaults.d.ts.map +1 -0
- package/dist/queue/defaults.js +205 -0
- package/dist/queue/defaults.js.map +1 -0
- package/dist/queue/index.d.ts +124 -0
- package/dist/queue/index.d.ts.map +1 -0
- package/dist/queue/index.js +116 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/queue.d.ts +156 -0
- package/dist/queue/queue.d.ts.map +1 -0
- package/dist/queue/queue.js +387 -0
- package/dist/queue/queue.js.map +1 -0
- package/dist/queue/transports/database.d.ts +165 -0
- package/dist/queue/transports/database.d.ts.map +1 -0
- package/dist/queue/transports/database.js +595 -0
- package/dist/queue/transports/database.js.map +1 -0
- package/dist/queue/transports/memory.d.ts +143 -0
- package/dist/queue/transports/memory.d.ts.map +1 -0
- package/dist/queue/transports/memory.js +415 -0
- package/dist/queue/transports/memory.js.map +1 -0
- package/dist/queue/transports/redis.d.ts +203 -0
- package/dist/queue/transports/redis.d.ts.map +1 -0
- package/dist/queue/transports/redis.js +744 -0
- package/dist/queue/transports/redis.js.map +1 -0
- package/dist/security/defaults.d.ts +64 -0
- package/dist/security/defaults.d.ts.map +1 -0
- package/dist/security/defaults.js +159 -0
- package/dist/security/defaults.js.map +1 -0
- package/dist/security/index.d.ts +110 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +160 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/security.d.ts +138 -0
- package/dist/security/security.d.ts.map +1 -0
- package/dist/security/security.js +419 -0
- package/dist/security/security.js.map +1 -0
- package/dist/storage/defaults.d.ts +79 -0
- package/dist/storage/defaults.d.ts.map +1 -0
- package/dist/storage/defaults.js +358 -0
- package/dist/storage/defaults.js.map +1 -0
- package/dist/storage/index.d.ts +153 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +242 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/storage.d.ts +151 -0
- package/dist/storage/storage.d.ts.map +1 -0
- package/dist/storage/storage.js +439 -0
- package/dist/storage/storage.js.map +1 -0
- package/dist/storage/strategies/local.d.ts +117 -0
- package/dist/storage/strategies/local.d.ts.map +1 -0
- package/dist/storage/strategies/local.js +368 -0
- package/dist/storage/strategies/local.js.map +1 -0
- package/dist/storage/strategies/r2.d.ts +130 -0
- package/dist/storage/strategies/r2.d.ts.map +1 -0
- package/dist/storage/strategies/r2.js +470 -0
- package/dist/storage/strategies/r2.js.map +1 -0
- package/dist/storage/strategies/s3.d.ts +121 -0
- package/dist/storage/strategies/s3.d.ts.map +1 -0
- package/dist/storage/strategies/s3.js +461 -0
- package/dist/storage/strategies/s3.js.map +1 -0
- package/dist/util/defaults.d.ts +77 -0
- package/dist/util/defaults.d.ts.map +1 -0
- package/dist/util/defaults.js +193 -0
- package/dist/util/defaults.js.map +1 -0
- package/dist/util/index.d.ts +97 -0
- package/dist/util/index.d.ts.map +1 -0
- package/dist/util/index.js +165 -0
- package/dist/util/index.js.map +1 -0
- package/dist/util/util.d.ts +145 -0
- package/dist/util/util.d.ts.map +1 -0
- package/dist/util/util.js +481 -0
- package/dist/util/util.js.map +1 -0
- package/package.json +234 -0
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core utility class with 12 essential JavaScript functions
|
|
3
|
+
* @module @bloomneo/appkit/util
|
|
4
|
+
* @file src/util/util.ts
|
|
5
|
+
*
|
|
6
|
+
* @llm-rule WHEN: Building apps that need common utility functions (get, chunk, slugify, debounce, etc.)
|
|
7
|
+
* @llm-rule AVOID: Using directly - always get instance via utilClass.get()
|
|
8
|
+
* @llm-rule NOTE: Provides 12 essential utilities: get, isEmpty, slugify, chunk, debounce, pick, unique, clamp, formatBytes, truncate, sleep, uuid
|
|
9
|
+
*/
|
|
10
|
+
import crypto from 'crypto';
|
|
11
|
+
import { createUtilityError as createError } from './defaults.js';
|
|
12
|
+
/**
|
|
13
|
+
* Utility class with 12 essential JavaScript functions
|
|
14
|
+
*/
|
|
15
|
+
export class UtilClass {
|
|
16
|
+
config;
|
|
17
|
+
memoCache;
|
|
18
|
+
debounceCache;
|
|
19
|
+
constructor(config) {
|
|
20
|
+
this.config = config;
|
|
21
|
+
this.memoCache = new Map();
|
|
22
|
+
this.debounceCache = new Map();
|
|
23
|
+
// Setup cache cleanup if enabled
|
|
24
|
+
if (config.cache.enabled) {
|
|
25
|
+
this.setupCacheCleanup();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Safe property access with dot notation and array indexing
|
|
30
|
+
* @llm-rule WHEN: Accessing nested object properties safely to prevent "Cannot read property of undefined" errors
|
|
31
|
+
* @llm-rule AVOID: Direct property access on potentially undefined objects - always use this for nested access
|
|
32
|
+
* @llm-rule NOTE: Supports array indexing, optional chaining syntax, and type-safe defaults
|
|
33
|
+
*/
|
|
34
|
+
get(obj, path, defaultValue, options = {}) {
|
|
35
|
+
if (!obj || typeof path !== 'string') {
|
|
36
|
+
return defaultValue;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
// Handle simple property access
|
|
40
|
+
if (!path.includes('.') && !path.includes('[')) {
|
|
41
|
+
const value = obj[path];
|
|
42
|
+
return value !== undefined ? value : defaultValue;
|
|
43
|
+
}
|
|
44
|
+
// Parse complex path with dots and brackets
|
|
45
|
+
const keys = this.parsePath(path);
|
|
46
|
+
let current = obj;
|
|
47
|
+
for (const key of keys) {
|
|
48
|
+
if (current == null) {
|
|
49
|
+
if (options.throwOnMissing) {
|
|
50
|
+
throw createError(`Property '${path}' not found`, 'get', { obj, path });
|
|
51
|
+
}
|
|
52
|
+
return defaultValue;
|
|
53
|
+
}
|
|
54
|
+
current = current[key];
|
|
55
|
+
}
|
|
56
|
+
return current !== undefined ? current : defaultValue;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (options.throwOnMissing) {
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
return defaultValue;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Universal empty check for all JavaScript values
|
|
67
|
+
* @llm-rule WHEN: Validating if any value is truly empty (null, undefined, {}, [], "", whitespace-only strings)
|
|
68
|
+
* @llm-rule AVOID: Manual empty checks like !value - this handles all edge cases properly
|
|
69
|
+
* @llm-rule NOTE: Returns true for null, undefined, {}, [], "", " ", false for 0 and false
|
|
70
|
+
*/
|
|
71
|
+
isEmpty(value) {
|
|
72
|
+
// null or undefined
|
|
73
|
+
if (value == null)
|
|
74
|
+
return true;
|
|
75
|
+
// Empty string or whitespace-only string
|
|
76
|
+
if (typeof value === 'string') {
|
|
77
|
+
return value.trim().length === 0;
|
|
78
|
+
}
|
|
79
|
+
// Arrays and array-like objects
|
|
80
|
+
if (Array.isArray(value) || typeof value.length === 'number') {
|
|
81
|
+
return value.length === 0;
|
|
82
|
+
}
|
|
83
|
+
// Objects (including Date, RegExp, etc.)
|
|
84
|
+
if (typeof value === 'object') {
|
|
85
|
+
// Handle special objects
|
|
86
|
+
if (value instanceof Date)
|
|
87
|
+
return false;
|
|
88
|
+
if (value instanceof RegExp)
|
|
89
|
+
return false;
|
|
90
|
+
if (value instanceof Set || value instanceof Map) {
|
|
91
|
+
return value.size === 0;
|
|
92
|
+
}
|
|
93
|
+
// Plain objects
|
|
94
|
+
return Object.keys(value).length === 0;
|
|
95
|
+
}
|
|
96
|
+
// Numbers, booleans, functions are not empty
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Convert text to URL-safe slugs
|
|
101
|
+
* @llm-rule WHEN: Creating URLs, filenames, or IDs from user text input
|
|
102
|
+
* @llm-rule AVOID: Manual string replacement - this handles unicode, special characters, and edge cases
|
|
103
|
+
* @llm-rule NOTE: Converts "Hello World! 123" to "hello-world-123", handles accents and special characters
|
|
104
|
+
*/
|
|
105
|
+
slugify(text, options = {}) {
|
|
106
|
+
if (typeof text !== 'string') {
|
|
107
|
+
return '';
|
|
108
|
+
}
|
|
109
|
+
const opts = {
|
|
110
|
+
replacement: options.replacement || this.config.slugify.replacement,
|
|
111
|
+
lowercase: options.lowercase !== false,
|
|
112
|
+
strict: options.strict || this.config.slugify.strict,
|
|
113
|
+
locale: options.locale || this.config.slugify.locale,
|
|
114
|
+
};
|
|
115
|
+
let result = text.toString();
|
|
116
|
+
// Convert to lowercase if requested
|
|
117
|
+
if (opts.lowercase) {
|
|
118
|
+
result = result.toLowerCase();
|
|
119
|
+
}
|
|
120
|
+
// Replace accented characters
|
|
121
|
+
result = result.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
|
122
|
+
// Replace special characters and spaces
|
|
123
|
+
if (opts.strict) {
|
|
124
|
+
result = result.replace(/[^a-zA-Z0-9]/g, opts.replacement);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
result = result
|
|
128
|
+
.replace(/[^a-zA-Z0-9\s-_]/g, '') // Remove special chars but keep spaces, hyphens, underscores
|
|
129
|
+
.replace(/\s+/g, opts.replacement); // Replace spaces with replacement
|
|
130
|
+
}
|
|
131
|
+
// Clean up multiple replacements and trim
|
|
132
|
+
result = result
|
|
133
|
+
.replace(new RegExp(`\\${opts.replacement}+`, 'g'), opts.replacement)
|
|
134
|
+
.replace(new RegExp(`^\\${opts.replacement}+|\\${opts.replacement}+$`, 'g'), '');
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Split array into smaller chunks of specified size
|
|
139
|
+
* @llm-rule WHEN: Processing large arrays in batches, creating pagination, or organizing data into grids
|
|
140
|
+
* @llm-rule AVOID: Manual array slicing - this handles edge cases and provides consistent behavior
|
|
141
|
+
* @llm-rule NOTE: chunk([1,2,3,4,5], 2) returns [[1,2], [3,4], [5]], handles empty arrays safely
|
|
142
|
+
*/
|
|
143
|
+
chunk(array, size, options = {}) {
|
|
144
|
+
if (!Array.isArray(array)) {
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
if (size <= 0) {
|
|
148
|
+
throw createError('Chunk size must be positive', 'chunk', { array, size });
|
|
149
|
+
}
|
|
150
|
+
if (array.length === 0) {
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
// Performance warning for large arrays
|
|
154
|
+
if (this.config.performance.enabled && array.length > this.config.performance.chunkSizeLimit) {
|
|
155
|
+
console.warn(`[VoilaJSX Utils] Chunking large array (${array.length} items). Consider streaming or pagination.`);
|
|
156
|
+
}
|
|
157
|
+
const result = [];
|
|
158
|
+
for (let i = 0; i < array.length; i += size) {
|
|
159
|
+
const chunk = array.slice(i, i + size);
|
|
160
|
+
// Fill incomplete chunks if requested
|
|
161
|
+
if (options.fillIncomplete && chunk.length < size && i + size >= array.length) {
|
|
162
|
+
const fillValue = options.fillValue;
|
|
163
|
+
while (chunk.length < size) {
|
|
164
|
+
chunk.push(fillValue);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
result.push(chunk);
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Debounce function calls to prevent excessive execution
|
|
173
|
+
* @llm-rule WHEN: Handling user input events (search, resize, scroll) to optimize performance
|
|
174
|
+
* @llm-rule AVOID: Manual setTimeout management - this handles cleanup and edge cases properly
|
|
175
|
+
* @llm-rule NOTE: Delays function execution until after specified wait period, cancels previous calls
|
|
176
|
+
*/
|
|
177
|
+
debounce(func, wait, options = {}) {
|
|
178
|
+
if (typeof func !== 'function') {
|
|
179
|
+
throw createError('Debounce target must be a function', 'debounce', func);
|
|
180
|
+
}
|
|
181
|
+
if (wait < 0) {
|
|
182
|
+
throw createError('Debounce wait time must be non-negative', 'debounce', wait);
|
|
183
|
+
}
|
|
184
|
+
const cacheKey = func.toString() + wait + JSON.stringify(options);
|
|
185
|
+
let timeoutId = null;
|
|
186
|
+
let lastArgs = [];
|
|
187
|
+
let lastThis;
|
|
188
|
+
let result;
|
|
189
|
+
const invokeFunc = () => {
|
|
190
|
+
result = func.apply(lastThis, lastArgs);
|
|
191
|
+
timeoutId = null;
|
|
192
|
+
return result;
|
|
193
|
+
};
|
|
194
|
+
const leadingEdge = () => {
|
|
195
|
+
if (options.leading) {
|
|
196
|
+
result = invokeFunc();
|
|
197
|
+
}
|
|
198
|
+
timeoutId = setTimeout(trailingEdge, wait);
|
|
199
|
+
return result;
|
|
200
|
+
};
|
|
201
|
+
const trailingEdge = () => {
|
|
202
|
+
timeoutId = null;
|
|
203
|
+
if (options.trailing !== false) {
|
|
204
|
+
result = invokeFunc();
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
};
|
|
208
|
+
const debounced = function (...args) {
|
|
209
|
+
lastArgs = args;
|
|
210
|
+
lastThis = this;
|
|
211
|
+
if (timeoutId === null) {
|
|
212
|
+
return leadingEdge();
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
clearTimeout(timeoutId);
|
|
216
|
+
timeoutId = setTimeout(trailingEdge, wait);
|
|
217
|
+
}
|
|
218
|
+
return result;
|
|
219
|
+
};
|
|
220
|
+
debounced.cancel = () => {
|
|
221
|
+
if (timeoutId !== null) {
|
|
222
|
+
clearTimeout(timeoutId);
|
|
223
|
+
timeoutId = null;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
debounced.flush = () => {
|
|
227
|
+
if (timeoutId !== null) {
|
|
228
|
+
clearTimeout(timeoutId);
|
|
229
|
+
return trailingEdge();
|
|
230
|
+
}
|
|
231
|
+
return result;
|
|
232
|
+
};
|
|
233
|
+
return debounced;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Extract specific properties from an object
|
|
237
|
+
* @llm-rule WHEN: Cleaning API responses, extracting specific data, or creating object subsets
|
|
238
|
+
* @llm-rule AVOID: Manual property extraction - this handles nested keys and edge cases
|
|
239
|
+
* @llm-rule NOTE: pick(user, ['id', 'name', 'email']) returns object with only specified properties
|
|
240
|
+
*/
|
|
241
|
+
pick(obj, keys) {
|
|
242
|
+
if (!obj || typeof obj !== 'object') {
|
|
243
|
+
return {};
|
|
244
|
+
}
|
|
245
|
+
if (!Array.isArray(keys)) {
|
|
246
|
+
throw createError('Keys must be an array', 'pick', { obj, keys });
|
|
247
|
+
}
|
|
248
|
+
const result = {};
|
|
249
|
+
for (const key of keys) {
|
|
250
|
+
if (key in obj) {
|
|
251
|
+
result[key] = obj[key];
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Remove duplicate values from array
|
|
258
|
+
* @llm-rule WHEN: Cleaning arrays with duplicate values, creating unique lists
|
|
259
|
+
* @llm-rule AVOID: Manual duplicate removal - this is optimized and handles all value types
|
|
260
|
+
* @llm-rule NOTE: Uses Set for performance, handles primitives and object references
|
|
261
|
+
*/
|
|
262
|
+
unique(array) {
|
|
263
|
+
if (!Array.isArray(array)) {
|
|
264
|
+
return [];
|
|
265
|
+
}
|
|
266
|
+
if (array.length === 0) {
|
|
267
|
+
return [];
|
|
268
|
+
}
|
|
269
|
+
// Use Set for performance with primitive values
|
|
270
|
+
if (array.length < 1000 || array.every(item => typeof item === 'string' ||
|
|
271
|
+
typeof item === 'number' ||
|
|
272
|
+
typeof item === 'boolean' ||
|
|
273
|
+
item === null ||
|
|
274
|
+
item === undefined)) {
|
|
275
|
+
return Array.from(new Set(array));
|
|
276
|
+
}
|
|
277
|
+
// Fallback for complex objects
|
|
278
|
+
const seen = new Map();
|
|
279
|
+
const result = [];
|
|
280
|
+
for (const item of array) {
|
|
281
|
+
const key = typeof item === 'object' && item !== null
|
|
282
|
+
? JSON.stringify(item)
|
|
283
|
+
: item;
|
|
284
|
+
if (!seen.has(key)) {
|
|
285
|
+
seen.set(key, true);
|
|
286
|
+
result.push(item);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return result;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Constrain number within specified bounds
|
|
293
|
+
* @llm-rule WHEN: Validating user input, constraining values for UI controls (volume, opacity, progress)
|
|
294
|
+
* @llm-rule AVOID: Manual min/max checking - this handles edge cases and type conversion
|
|
295
|
+
* @llm-rule NOTE: clamp(150, 0, 100) returns 100, clamp(-10, 0, 100) returns 0
|
|
296
|
+
*/
|
|
297
|
+
clamp(value, min, max) {
|
|
298
|
+
if (typeof value !== 'number' || isNaN(value)) {
|
|
299
|
+
throw createError('Value must be a valid number', 'clamp', { value, min, max });
|
|
300
|
+
}
|
|
301
|
+
if (typeof min !== 'number' || typeof max !== 'number') {
|
|
302
|
+
throw createError('Min and max must be valid numbers', 'clamp', { value, min, max });
|
|
303
|
+
}
|
|
304
|
+
if (min > max) {
|
|
305
|
+
throw createError('Min value cannot be greater than max value', 'clamp', { value, min, max });
|
|
306
|
+
}
|
|
307
|
+
return Math.min(Math.max(value, min), max);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Format byte sizes in human-readable format
|
|
311
|
+
* @llm-rule WHEN: Displaying file sizes, memory usage, or data transfer amounts
|
|
312
|
+
* @llm-rule AVOID: Manual byte formatting - this handles all units and edge cases properly
|
|
313
|
+
* @llm-rule NOTE: formatBytes(1024) returns "1 KB", formatBytes(0) returns "0 Bytes"
|
|
314
|
+
*/
|
|
315
|
+
formatBytes(bytes, options = {}) {
|
|
316
|
+
if (typeof bytes !== 'number' || isNaN(bytes)) {
|
|
317
|
+
return '0 Bytes';
|
|
318
|
+
}
|
|
319
|
+
if (bytes === 0) {
|
|
320
|
+
return '0 Bytes';
|
|
321
|
+
}
|
|
322
|
+
const decimals = options.decimals !== undefined ? options.decimals : 2;
|
|
323
|
+
const binary = options.binary !== false; // Default to binary (1024)
|
|
324
|
+
const unitSeparator = options.unitSeparator || ' ';
|
|
325
|
+
const base = binary ? 1024 : 1000;
|
|
326
|
+
const units = binary
|
|
327
|
+
? ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
|
328
|
+
: ['Bytes', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
329
|
+
const absBytes = Math.abs(bytes);
|
|
330
|
+
const unitIndex = Math.floor(Math.log(absBytes) / Math.log(base));
|
|
331
|
+
const clampedIndex = Math.min(unitIndex, units.length - 1);
|
|
332
|
+
const value = bytes / Math.pow(base, clampedIndex);
|
|
333
|
+
const formattedValue = clampedIndex === 0
|
|
334
|
+
? value.toString()
|
|
335
|
+
: value.toFixed(decimals);
|
|
336
|
+
return `${formattedValue}${unitSeparator}${units[clampedIndex]}`;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Truncate text with intelligent word boundary detection
|
|
340
|
+
* @llm-rule WHEN: Displaying text previews, card descriptions, or mobile content
|
|
341
|
+
* @llm-rule AVOID: Simple string.slice() - this preserves words and handles edge cases
|
|
342
|
+
* @llm-rule NOTE: truncate("Hello World", 8) returns "Hello...", respects word boundaries
|
|
343
|
+
*/
|
|
344
|
+
truncate(text, options) {
|
|
345
|
+
if (typeof text !== 'string') {
|
|
346
|
+
return '';
|
|
347
|
+
}
|
|
348
|
+
const { length, suffix = '...', separator, preserveWords = true } = options;
|
|
349
|
+
if (length <= 0) {
|
|
350
|
+
return '';
|
|
351
|
+
}
|
|
352
|
+
if (text.length <= length) {
|
|
353
|
+
return text;
|
|
354
|
+
}
|
|
355
|
+
let truncated = text.slice(0, length - suffix.length);
|
|
356
|
+
// Preserve word boundaries
|
|
357
|
+
if (preserveWords && truncated.length > 0) {
|
|
358
|
+
const lastSpace = truncated.lastIndexOf(' ');
|
|
359
|
+
if (lastSpace > length * 0.5) { // Only if we don't lose too much content
|
|
360
|
+
truncated = truncated.slice(0, lastSpace);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// Handle custom separator
|
|
364
|
+
if (separator) {
|
|
365
|
+
const lastSeparator = truncated.lastIndexOf(separator);
|
|
366
|
+
if (lastSeparator > 0) {
|
|
367
|
+
truncated = truncated.slice(0, lastSeparator);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return truncated + suffix;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Promise-based sleep function for async delays
|
|
374
|
+
* @llm-rule WHEN: Adding delays in async functions, rate limiting, or animation timing
|
|
375
|
+
* @llm-rule AVOID: setTimeout in async/await contexts - this provides clean Promise-based delays
|
|
376
|
+
* @llm-rule NOTE: await sleep(1000) pauses execution for 1 second without blocking the event loop
|
|
377
|
+
*/
|
|
378
|
+
sleep(ms) {
|
|
379
|
+
if (typeof ms !== 'number' || ms < 0 || isNaN(ms)) {
|
|
380
|
+
throw createError('Sleep duration must be a non-negative number', 'sleep', ms);
|
|
381
|
+
}
|
|
382
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Generate RFC4122 version 4 UUID
|
|
386
|
+
* @llm-rule WHEN: Creating unique identifiers for sessions, temporary keys, or object IDs
|
|
387
|
+
* @llm-rule AVOID: Manual ID generation - this provides cryptographically secure UUIDs
|
|
388
|
+
* @llm-rule NOTE: Returns standard UUID format: "f47ac10b-58cc-4372-a567-0e02b2c3d479"
|
|
389
|
+
*/
|
|
390
|
+
uuid() {
|
|
391
|
+
try {
|
|
392
|
+
// Use crypto.randomUUID if available (Node.js 14.17.0+, modern browsers)
|
|
393
|
+
if (typeof crypto.randomUUID === 'function') {
|
|
394
|
+
return crypto.randomUUID();
|
|
395
|
+
}
|
|
396
|
+
// Fallback implementation
|
|
397
|
+
const bytes = crypto.randomBytes(16);
|
|
398
|
+
// Set version (4) and variant bits
|
|
399
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
400
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
401
|
+
const hex = bytes.toString('hex');
|
|
402
|
+
return [
|
|
403
|
+
hex.slice(0, 8),
|
|
404
|
+
hex.slice(8, 12),
|
|
405
|
+
hex.slice(12, 16),
|
|
406
|
+
hex.slice(16, 20),
|
|
407
|
+
hex.slice(20, 32)
|
|
408
|
+
].join('-');
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
throw createError('Failed to generate UUID', 'uuid', error);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// Private helper methods
|
|
415
|
+
/**
|
|
416
|
+
* Parse object path with dot notation and array indexing
|
|
417
|
+
*/
|
|
418
|
+
parsePath(path) {
|
|
419
|
+
const keys = [];
|
|
420
|
+
let current = '';
|
|
421
|
+
let inBrackets = false;
|
|
422
|
+
for (let i = 0; i < path.length; i++) {
|
|
423
|
+
const char = path[i];
|
|
424
|
+
if (char === '[') {
|
|
425
|
+
if (current) {
|
|
426
|
+
keys.push(current);
|
|
427
|
+
current = '';
|
|
428
|
+
}
|
|
429
|
+
inBrackets = true;
|
|
430
|
+
}
|
|
431
|
+
else if (char === ']') {
|
|
432
|
+
if (inBrackets && current) {
|
|
433
|
+
// Try to parse as number for array index
|
|
434
|
+
const num = parseInt(current, 10);
|
|
435
|
+
keys.push(isNaN(num) ? current : num);
|
|
436
|
+
current = '';
|
|
437
|
+
}
|
|
438
|
+
inBrackets = false;
|
|
439
|
+
}
|
|
440
|
+
else if (char === '.' && !inBrackets) {
|
|
441
|
+
if (current) {
|
|
442
|
+
keys.push(current);
|
|
443
|
+
current = '';
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
current += char;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (current) {
|
|
451
|
+
keys.push(current);
|
|
452
|
+
}
|
|
453
|
+
return keys;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Setup automatic cache cleanup
|
|
457
|
+
*/
|
|
458
|
+
setupCacheCleanup() {
|
|
459
|
+
if (!this.config.cache.enabled)
|
|
460
|
+
return;
|
|
461
|
+
const cleanupInterval = Math.min(this.config.cache.ttl, 60000); // Max 1 minute
|
|
462
|
+
setInterval(() => {
|
|
463
|
+
const now = Date.now();
|
|
464
|
+
for (const [key, entry] of this.memoCache.entries()) {
|
|
465
|
+
if (now - entry.timestamp > this.config.cache.ttl) {
|
|
466
|
+
this.memoCache.delete(key);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
// Enforce max size
|
|
470
|
+
if (this.memoCache.size > this.config.cache.maxSize) {
|
|
471
|
+
const entries = Array.from(this.memoCache.entries());
|
|
472
|
+
entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
|
|
473
|
+
const toDelete = entries.slice(0, this.memoCache.size - this.config.cache.maxSize);
|
|
474
|
+
for (const [key] of toDelete) {
|
|
475
|
+
this.memoCache.delete(key);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}, cleanupInterval).unref?.();
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
//# sourceMappingURL=util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/util/util.ts"],"names":[],"mappings":"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"}
|