@ylsoo/core 1.1.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,43 @@
1
+ class YlsooHelpers {
2
+ sleep(ms) {
3
+ return new Promise(resolve => setTimeout(resolve, ms));
4
+ }
5
+
6
+ deepClone(obj) {
7
+ if (typeof structuredClone === 'function') {
8
+ return structuredClone(obj);
9
+ }
10
+ return JSON.parse(JSON.stringify(obj));
11
+ }
12
+
13
+ debounce(func, wait) {
14
+ let timeout;
15
+ return function executedFunction(...args) {
16
+ const later = () => {
17
+ clearTimeout(timeout);
18
+ func(...args);
19
+ };
20
+ clearTimeout(timeout);
21
+ timeout = setTimeout(later, wait);
22
+ };
23
+ }
24
+
25
+ isEmpty(value) {
26
+ if (value === null || value === undefined) return true;
27
+ if (typeof value === 'string' || Array.isArray(value)) return value.length === 0;
28
+ if (typeof value === 'object') {
29
+ if (value instanceof Map || value instanceof Set) return value.size === 0;
30
+ return Object.keys(value).length === 0;
31
+ }
32
+ return false;
33
+ }
34
+
35
+ capitalize(str) {
36
+ if (typeof str !== 'string' || str.length === 0) {
37
+ return str;
38
+ }
39
+ return str.charAt(0).toUpperCase() + str.slice(1);
40
+ }
41
+ }
42
+
43
+ module.exports = { YlsooHelpers };
@@ -0,0 +1,50 @@
1
+ class YlsooTaskQueue {
2
+ /**
3
+ * Limit concurrency of massive promises automatically
4
+ * @param {number} concurrencyLimit
5
+ */
6
+ constructor(concurrencyLimit = 5) {
7
+ this.concurrencyLimit = concurrencyLimit;
8
+ this.activeCount = 0;
9
+ this.queue = [];
10
+ }
11
+
12
+ /**
13
+ * Add a function that returns a Promise to the queue
14
+ * @param {Function} asyncTask
15
+ * @returns {Promise<*>}
16
+ */
17
+ add(asyncTask) {
18
+ return new Promise((resolve, reject) => {
19
+ this.queue.push({
20
+ task: asyncTask,
21
+ resolve,
22
+ reject
23
+ });
24
+ this._next();
25
+ });
26
+ }
27
+
28
+ get remaining() {
29
+ return this.queue.length;
30
+ }
31
+
32
+ _next() {
33
+ if (this.activeCount >= this.concurrencyLimit || this.queue.length === 0) {
34
+ return;
35
+ }
36
+
37
+ this.activeCount++;
38
+ const { task, resolve, reject } = this.queue.shift();
39
+
40
+ task()
41
+ .then(resolve)
42
+ .catch(reject)
43
+ .finally(() => {
44
+ this.activeCount--;
45
+ this._next();
46
+ });
47
+ }
48
+ }
49
+
50
+ module.exports = { YlsooTaskQueue };
@@ -0,0 +1,46 @@
1
+ class YlsooTime {
2
+ /**
3
+ * Extremely lightweight date formatter (replaces heavy Moment.js)
4
+ * @param {Date|number|string} date
5
+ * @param {string} formatStr (e.g. "YYYY-MM-DD HH:mm:ss")
6
+ */
7
+ format(date, formatStr = "YYYY-MM-DD") {
8
+ const d = new Date(date);
9
+ if (isNaN(d.getTime())) return null;
10
+
11
+ const pad = (n) => String(n).padStart(2, '0');
12
+
13
+ return formatStr
14
+ .replace('YYYY', d.getFullYear())
15
+ .replace('YY', String(d.getFullYear()).slice(-2))
16
+ .replace('MM', pad(d.getMonth() + 1))
17
+ .replace('DD', pad(d.getDate()))
18
+ .replace('HH', pad(d.getHours()))
19
+ .replace('mm', pad(d.getMinutes()))
20
+ .replace('ss', pad(d.getSeconds()));
21
+ }
22
+
23
+ /**
24
+ * Fast "time ago" algorithm
25
+ * @param {Date|number|string} date
26
+ */
27
+ timeAgo(date) {
28
+ const d = new Date(date);
29
+ const seconds = Math.floor((new Date() - d) / 1000);
30
+
31
+ let interval = Math.floor(seconds / 31536000);
32
+ if (interval >= 1) return interval + " year" + (interval > 1 ? "s" : "") + " ago";
33
+ interval = Math.floor(seconds / 2592000);
34
+ if (interval >= 1) return interval + " month" + (interval > 1 ? "s" : "") + " ago";
35
+ interval = Math.floor(seconds / 86400);
36
+ if (interval >= 1) return interval + " day" + (interval > 1 ? "s" : "") + " ago";
37
+ interval = Math.floor(seconds / 3600);
38
+ if (interval >= 1) return interval + " hour" + (interval > 1 ? "s" : "") + " ago";
39
+ interval = Math.floor(seconds / 60);
40
+ if (interval >= 1) return interval + " minute" + (interval > 1 ? "s" : "") + " ago";
41
+
42
+ return Math.floor(seconds) + " seconds ago";
43
+ }
44
+ }
45
+
46
+ module.exports = { YlsooTime };
@@ -0,0 +1,53 @@
1
+ class YlsooValidator {
2
+ /**
3
+ * Validate an object against a strict schema mapping
4
+ * @param {*} data
5
+ * @param {object} schema
6
+ * @throws Error on validation failure
7
+ * @returns {boolean} true if valid
8
+ */
9
+ validate(data, schema) {
10
+ if (typeof data !== 'object' || data === null) {
11
+ throw new Error('[Ylsoo Validation] Target is not an object.');
12
+ }
13
+
14
+ for (const [key, rules] of Object.entries(schema)) {
15
+ const value = data[key];
16
+
17
+ // Handle raw type strings (e.g. { age: 'number' })
18
+ const type = typeof rules === 'string' ? rules : rules.type;
19
+
20
+ // Check required
21
+ const isRequired = typeof rules === 'object' ? rules.required !== false : true;
22
+ if (value === undefined || value === null) {
23
+ if (isRequired) throw new Error(`[Ylsoo Validation] Missing required key: ${key}`);
24
+ continue;
25
+ }
26
+
27
+ // Check Types
28
+ if (type === 'array') {
29
+ if (!Array.isArray(value)) throw new Error(`[Ylsoo Validation] Type mismatch. ${key} must be an array.`);
30
+ } else if (type === 'email') {
31
+ if (typeof value !== 'string' || !/^\S+@\S+\.\S+$/.test(value)) {
32
+ throw new Error(`[Ylsoo Validation] Type mismatch. ${key} must be a valid email.`);
33
+ }
34
+ } else if (type === 'object') {
35
+ if (typeof value !== 'object' || Array.isArray(value)) {
36
+ throw new Error(`[Ylsoo Validation] Type mismatch. ${key} must be an object.`);
37
+ }
38
+ // Recursive dive
39
+ if (rules.schema) {
40
+ this.validate(value, rules.schema);
41
+ }
42
+ } else {
43
+ if (typeof value !== type) {
44
+ throw new Error(`[Ylsoo Validation] Type mismatch. ${key} must be a ${type}.`);
45
+ }
46
+ }
47
+ }
48
+
49
+ return true;
50
+ }
51
+ }
52
+
53
+ module.exports = { YlsooValidator };
package/index.js DELETED
@@ -1,202 +0,0 @@
1
- /**
2
- * @ylsoo/core
3
- * Premium utility functions for Ylsoo projects
4
- * Zero dependency, extremely fast, robust.
5
- */
6
-
7
- class YlsooLogger {
8
- constructor() {
9
- this.colors = {
10
- reset: "\x1b[0m",
11
- info: "\x1b[36m", // Cyan
12
- success: "\x1b[32m", // Green
13
- warn: "\x1b[33m", // Yellow
14
- error: "\x1b[31m", // Red
15
- ylsoo: "\x1b[35m" // Magenta
16
- };
17
- }
18
-
19
- _format(level, message, color) {
20
- const time = new Date().toISOString().split('T')[1].slice(0, -1);
21
- return `${this.colors.ylsoo}[Ylsoo]${this.colors.reset} ${color}[${level.toUpperCase()}]${this.colors.reset} ${message}`;
22
- }
23
-
24
- info(message) {
25
- console.log(this._format('info', message, this.colors.info));
26
- }
27
-
28
- success(message) {
29
- console.log(this._format('success', message, this.colors.success));
30
- }
31
-
32
- warn(message) {
33
- console.warn(this._format('warn', message, this.colors.warn));
34
- }
35
-
36
- error(message) {
37
- console.error(this._format('error', message, this.colors.error));
38
- }
39
- }
40
-
41
- class YlsooCache {
42
- constructor() {
43
- this.store = new Map();
44
- }
45
-
46
- /**
47
- * Set a key-value pair with an optional Time-To-Live
48
- * @param {string} key
49
- * @param {*} value
50
- * @param {number} ttlMs - Time to live in milliseconds
51
- */
52
- set(key, value, ttlMs = 0) {
53
- const expiresAt = ttlMs > 0 ? Date.now() + ttlMs : null;
54
- this.store.set(key, { value, expiresAt });
55
- }
56
-
57
- get(key) {
58
- const item = this.store.get(key);
59
- if (!item) return null;
60
-
61
- if (item.expiresAt && Date.now() > item.expiresAt) {
62
- this.store.delete(key);
63
- return null;
64
- }
65
- return item.value;
66
- }
67
-
68
- delete(key) {
69
- return this.store.delete(key);
70
- }
71
-
72
- clear() {
73
- this.store.clear();
74
- }
75
- }
76
-
77
- class YlsooHttp {
78
- /**
79
- * Premium wrapper for fetch
80
- * @param {string} endpoint
81
- * @param {object} options
82
- * @returns {Promise<any>}
83
- */
84
- async request(endpoint, options = {}) {
85
- const defaultHeaders = {
86
- 'Content-Type': 'application/json',
87
- 'User-Agent': 'Ylsoo-Core/1.1'
88
- };
89
-
90
- const config = {
91
- ...options,
92
- headers: {
93
- ...defaultHeaders,
94
- ...options.headers
95
- }
96
- };
97
-
98
- if (config.body && typeof config.body === 'object') {
99
- config.body = JSON.stringify(config.body);
100
- }
101
-
102
- try {
103
- const response = await fetch(endpoint, config);
104
- const isJson = response.headers.get('content-type')?.includes('application/json');
105
-
106
- const data = isJson ? await response.json() : await response.text();
107
-
108
- if (!response.ok) {
109
- throw {
110
- status: response.status,
111
- message: response.statusText,
112
- data
113
- };
114
- }
115
-
116
- return data;
117
- } catch (error) {
118
- throw new Error(`[Ylsoo HTTP Error]: ${error.message || JSON.stringify(error)}`);
119
- }
120
- }
121
-
122
- get(endpoint, headers = {}) {
123
- return this.request(endpoint, { method: 'GET', headers });
124
- }
125
-
126
- post(endpoint, body, headers = {}) {
127
- return this.request(endpoint, { method: 'POST', body, headers });
128
- }
129
- }
130
-
131
- class YlsooCore {
132
- constructor() {
133
- this.version = '1.1.0';
134
- this.logger = new YlsooLogger();
135
- this.cache = new YlsooCache();
136
- this.http = new YlsooHttp();
137
- }
138
-
139
- /**
140
- * Sleep for a given amount of time (Promise based)
141
- * @param {number} ms
142
- */
143
- sleep(ms) {
144
- return new Promise(resolve => setTimeout(resolve, ms));
145
- }
146
-
147
- /**
148
- * Deep clone an object natively
149
- * @param {object} obj
150
- */
151
- deepClone(obj) {
152
- if (typeof structuredClone === 'function') {
153
- return structuredClone(obj);
154
- }
155
- return JSON.parse(JSON.stringify(obj));
156
- }
157
-
158
- /**
159
- * Creates a debounced function that delays invoking func until after wait milliseconds have elapsed
160
- * @param {Function} func
161
- * @param {number} wait
162
- */
163
- debounce(func, wait) {
164
- let timeout;
165
- return function executedFunction(...args) {
166
- const later = () => {
167
- clearTimeout(timeout);
168
- func(...args);
169
- };
170
- clearTimeout(timeout);
171
- timeout = setTimeout(later, wait);
172
- };
173
- }
174
-
175
- /**
176
- * Simple utility to verify if a value is semantically empty
177
- * @param {*} value
178
- */
179
- isEmpty(value) {
180
- if (value === null || value === undefined) return true;
181
- if (typeof value === 'string' || Array.isArray(value)) return value.length === 0;
182
- if (typeof value === 'object') {
183
- if (value instanceof Map || value instanceof Set) return value.size === 0;
184
- return Object.keys(value).length === 0;
185
- }
186
- return false;
187
- }
188
-
189
- /**
190
- * Simple utility to capitalize a string
191
- * @param {string} str - The string to capitalize
192
- * @returns {string} Capitalized string
193
- */
194
- capitalize(str) {
195
- if (typeof str !== 'string' || str.length === 0) {
196
- return str;
197
- }
198
- return str.charAt(0).toUpperCase() + str.slice(1);
199
- }
200
- }
201
-
202
- module.exports = new YlsooCore();