@zairakai/js-utils 1.0.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.
- package/LICENSE +21 -0
- package/README.md +270 -0
- package/dist/arrays.cjs +210 -0
- package/dist/arrays.d.cts +119 -0
- package/dist/arrays.d.ts +119 -0
- package/dist/arrays.js +32 -0
- package/dist/chunk-27YHP2CK.js +407 -0
- package/dist/chunk-3WNRYKPG.js +37 -0
- package/dist/chunk-42CHLXT7.js +214 -0
- package/dist/chunk-6F4PWJZI.js +0 -0
- package/dist/chunk-7SXRFZBB.js +173 -0
- package/dist/chunk-F6RSTW65.js +156 -0
- package/dist/chunk-G7ZJ23DW.js +253 -0
- package/dist/chunk-IPP7PA6H.js +136 -0
- package/dist/chunk-LDSWHSRX.js +96 -0
- package/dist/chunk-TY75OOIQ.js +700 -0
- package/dist/chunk-W6JEMFAF.js +54 -0
- package/dist/chunk-XEJLBAXE.js +164 -0
- package/dist/chunk-Z7G3SIQH.js +270 -0
- package/dist/chunk-ZJPKS2MQ.js +101 -0
- package/dist/collections.cjs +797 -0
- package/dist/collections.d.cts +353 -0
- package/dist/collections.d.ts +353 -0
- package/dist/collections.js +17 -0
- package/dist/datetime.cjs +80 -0
- package/dist/datetime.d.cts +75 -0
- package/dist/datetime.d.ts +75 -0
- package/dist/datetime.js +24 -0
- package/dist/equals.cjs +121 -0
- package/dist/equals.d.cts +24 -0
- package/dist/equals.d.ts +24 -0
- package/dist/equals.js +8 -0
- package/dist/formatters.cjs +201 -0
- package/dist/formatters.d.cts +180 -0
- package/dist/formatters.d.ts +180 -0
- package/dist/formatters.js +48 -0
- package/dist/index.cjs +2906 -0
- package/dist/index.d.cts +120 -0
- package/dist/index.d.ts +120 -0
- package/dist/index.js +348 -0
- package/dist/number.cjs +279 -0
- package/dist/number.d.cts +177 -0
- package/dist/number.d.ts +177 -0
- package/dist/number.js +10 -0
- package/dist/obj.cjs +427 -0
- package/dist/obj.d.cts +177 -0
- package/dist/obj.d.ts +177 -0
- package/dist/obj.js +12 -0
- package/dist/php-arrays.cjs +954 -0
- package/dist/php-arrays.d.cts +256 -0
- package/dist/php-arrays.d.ts +256 -0
- package/dist/php-arrays.js +70 -0
- package/dist/runtime.cjs +134 -0
- package/dist/runtime.d.cts +90 -0
- package/dist/runtime.d.ts +90 -0
- package/dist/runtime.js +24 -0
- package/dist/schemas.cjs +86 -0
- package/dist/schemas.d.cts +108 -0
- package/dist/schemas.d.ts +108 -0
- package/dist/schemas.js +22 -0
- package/dist/str.cjs +499 -0
- package/dist/str.d.cts +282 -0
- package/dist/str.d.ts +282 -0
- package/dist/str.js +11 -0
- package/dist/types.cjs +18 -0
- package/dist/types.d.cts +13 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.js +1 -0
- package/dist/validator.cjs +251 -0
- package/dist/validator.d.cts +99 -0
- package/dist/validator.d.ts +99 -0
- package/dist/validator.js +11 -0
- package/dist/validators.cjs +217 -0
- package/dist/validators.d.cts +216 -0
- package/dist/validators.d.ts +216 -0
- package/dist/validators.js +64 -0
- package/package.json +180 -0
- package/src/arrays.ts +316 -0
- package/src/collections.ts +866 -0
- package/src/datetime.ts +103 -0
- package/src/equals.ts +134 -0
- package/src/formatters.ts +342 -0
- package/src/index.ts +36 -0
- package/src/number.ts +281 -0
- package/src/obj.ts +303 -0
- package/src/php-arrays.ts +445 -0
- package/src/pipe.ts +29 -0
- package/src/runtime.ts +194 -0
- package/src/schemas.ts +136 -0
- package/src/str.ts +438 -0
- package/src/types.ts +13 -0
- package/src/validator.ts +157 -0
- package/src/validators.ts +359 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/schemas.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var EmailSchema = z.string().email("Invalid email format").min(1, "Email is required");
|
|
4
|
+
var PhoneSchema = z.string().regex(/^\+?[1-9]\d{1,14}$/, "Invalid phone number format");
|
|
5
|
+
var UrlSchema = z.string().url("Invalid URL format");
|
|
6
|
+
var DateSchema = z.union([
|
|
7
|
+
z.string().datetime(),
|
|
8
|
+
z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Invalid date format (YYYY-MM-DD)"),
|
|
9
|
+
z.date()
|
|
10
|
+
]);
|
|
11
|
+
var ApiResponseSchema = (dataSchema) => z.object({
|
|
12
|
+
success: z.boolean(),
|
|
13
|
+
data: dataSchema.optional(),
|
|
14
|
+
message: z.string().optional(),
|
|
15
|
+
errors: z.array(z.string()).optional()
|
|
16
|
+
});
|
|
17
|
+
var PaginationSchema = z.object({
|
|
18
|
+
page: z.number().int().positive().default(1),
|
|
19
|
+
perPage: z.number().int().min(1).max(100).default(15),
|
|
20
|
+
total: z.number().int().nonnegative(),
|
|
21
|
+
lastPage: z.number().int().positive()
|
|
22
|
+
});
|
|
23
|
+
var PaginatedResponseSchema = (itemSchema) => z.object({
|
|
24
|
+
data: z.array(itemSchema),
|
|
25
|
+
pagination: PaginationSchema
|
|
26
|
+
});
|
|
27
|
+
var validateSchema = (schema, data) => {
|
|
28
|
+
const result = schema.safeParse(data);
|
|
29
|
+
if (!result.success) {
|
|
30
|
+
const errors = result.error.issues.map((err) => `${err.path.join(".")}: ${err.message}`);
|
|
31
|
+
throw new Error(`Validation failed: ${errors.join(", ")}`);
|
|
32
|
+
}
|
|
33
|
+
return result.data;
|
|
34
|
+
};
|
|
35
|
+
var safeValidateSchema = (schema, data) => {
|
|
36
|
+
const result = schema.safeParse(data);
|
|
37
|
+
if (result.success) {
|
|
38
|
+
return { success: true, data: result.data };
|
|
39
|
+
}
|
|
40
|
+
const errors = result.error.issues.map((err) => `${err.path.join(".")}: ${err.message}`);
|
|
41
|
+
return { success: false, errors };
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
EmailSchema,
|
|
46
|
+
PhoneSchema,
|
|
47
|
+
UrlSchema,
|
|
48
|
+
DateSchema,
|
|
49
|
+
ApiResponseSchema,
|
|
50
|
+
PaginationSchema,
|
|
51
|
+
PaginatedResponseSchema,
|
|
52
|
+
validateSchema,
|
|
53
|
+
safeValidateSchema
|
|
54
|
+
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// src/validators.ts
|
|
2
|
+
var isTrue = (value) => true === value;
|
|
3
|
+
var isFalse = (value) => false === value;
|
|
4
|
+
var isNull = (value) => null === value;
|
|
5
|
+
var isUndefined = (value) => void 0 === value;
|
|
6
|
+
var isSet = (value) => void 0 !== value && null !== value;
|
|
7
|
+
var isArray = (value) => Array.isArray(value);
|
|
8
|
+
var isObject = (value) => "object" === typeof value && null !== value && !Array.isArray(value);
|
|
9
|
+
var isString = (value) => "string" === typeof value;
|
|
10
|
+
var isNumber = (value) => "number" === typeof value && !isNaN(value);
|
|
11
|
+
var isInteger = (value) => Number.isInteger(value);
|
|
12
|
+
var isFloat = (value) => "number" === typeof value && !isNaN(value) && !Number.isInteger(value);
|
|
13
|
+
var isBoolean = (value) => "boolean" === typeof value;
|
|
14
|
+
var isFunction = (value) => "function" === typeof value;
|
|
15
|
+
var isDate = (value) => value instanceof Date && !isNaN(value.getTime());
|
|
16
|
+
var isNumeric = (value) => {
|
|
17
|
+
if ("number" === typeof value) {
|
|
18
|
+
return !isNaN(value) && isFinite(value);
|
|
19
|
+
}
|
|
20
|
+
if ("string" === typeof value) {
|
|
21
|
+
const num = Number(value.trim());
|
|
22
|
+
return "" !== value.trim() && !isNaN(num) && isFinite(num);
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
};
|
|
26
|
+
var isEmail = (value) => {
|
|
27
|
+
if ("string" !== typeof value) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
31
|
+
return emailRegex.test(value);
|
|
32
|
+
};
|
|
33
|
+
var isUrl = (value) => {
|
|
34
|
+
if ("string" !== typeof value) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
new URL(value);
|
|
39
|
+
return true;
|
|
40
|
+
} catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var isEmpty = (value) => {
|
|
45
|
+
if (isNull(value) || isUndefined(value)) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
if (isString(value)) {
|
|
49
|
+
return 0 === value.trim().length;
|
|
50
|
+
}
|
|
51
|
+
if (isArray(value)) {
|
|
52
|
+
return 0 === value.length;
|
|
53
|
+
}
|
|
54
|
+
if (isObject(value)) {
|
|
55
|
+
return 0 === Object.keys(value).length;
|
|
56
|
+
}
|
|
57
|
+
if (isNumber(value)) {
|
|
58
|
+
return 0 === value;
|
|
59
|
+
}
|
|
60
|
+
if (isBoolean(value)) {
|
|
61
|
+
return isFalse(value);
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
};
|
|
65
|
+
var isNotEmpty = (value) => !isEmpty(value);
|
|
66
|
+
var isBlank = (value) => {
|
|
67
|
+
if (value == null) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
if ("string" === typeof value) {
|
|
71
|
+
return "" === value.trim();
|
|
72
|
+
}
|
|
73
|
+
return isEmpty(value);
|
|
74
|
+
};
|
|
75
|
+
var isPresent = (value) => !isBlank(value);
|
|
76
|
+
var filled = (value) => isPresent(value);
|
|
77
|
+
var blank = (value) => isBlank(value);
|
|
78
|
+
var isEven = (value) => {
|
|
79
|
+
return isNumber(value) && 0 === value % 2;
|
|
80
|
+
};
|
|
81
|
+
var isOdd = (value) => {
|
|
82
|
+
return isNumber(value) && 0 !== value % 2;
|
|
83
|
+
};
|
|
84
|
+
var isJson = (value) => {
|
|
85
|
+
if ("string" !== typeof value) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
JSON.parse(value);
|
|
90
|
+
return true;
|
|
91
|
+
} catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
var isBase64 = (value) => {
|
|
96
|
+
if ("string" !== typeof value) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
const base64Pattern = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
100
|
+
if (0 !== value.length % 4) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return base64Pattern.test(value);
|
|
104
|
+
};
|
|
105
|
+
var isMacAddress = (value) => {
|
|
106
|
+
if ("string" !== typeof value) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
const macPattern = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
|
|
110
|
+
return macPattern.test(value);
|
|
111
|
+
};
|
|
112
|
+
var isUuid = (value) => {
|
|
113
|
+
if ("string" !== typeof value) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
|
|
117
|
+
};
|
|
118
|
+
var isIp = (value) => {
|
|
119
|
+
if ("string" !== typeof value) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
const ipv4 = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
|
|
123
|
+
if (ipv4.test(value)) {
|
|
124
|
+
return value.split(".").every((part) => {
|
|
125
|
+
const n = Number(part);
|
|
126
|
+
return n >= 0 && n <= 255 && String(n) === part;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|(([0-9a-fA-F]{1,4}:){0,7}:)|(:[0-9a-fA-F]{1,4}){1,7}|(([0-9a-fA-F]{1,4}:){1,7}:)|(([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4})|::1)$/;
|
|
130
|
+
return ipv6.test(value);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export {
|
|
134
|
+
isTrue,
|
|
135
|
+
isFalse,
|
|
136
|
+
isNull,
|
|
137
|
+
isUndefined,
|
|
138
|
+
isSet,
|
|
139
|
+
isArray,
|
|
140
|
+
isObject,
|
|
141
|
+
isString,
|
|
142
|
+
isNumber,
|
|
143
|
+
isInteger,
|
|
144
|
+
isFloat,
|
|
145
|
+
isBoolean,
|
|
146
|
+
isFunction,
|
|
147
|
+
isDate,
|
|
148
|
+
isNumeric,
|
|
149
|
+
isEmail,
|
|
150
|
+
isUrl,
|
|
151
|
+
isEmpty,
|
|
152
|
+
isNotEmpty,
|
|
153
|
+
isBlank,
|
|
154
|
+
isPresent,
|
|
155
|
+
filled,
|
|
156
|
+
blank,
|
|
157
|
+
isEven,
|
|
158
|
+
isOdd,
|
|
159
|
+
isJson,
|
|
160
|
+
isBase64,
|
|
161
|
+
isMacAddress,
|
|
162
|
+
isUuid,
|
|
163
|
+
isIp
|
|
164
|
+
};
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import {
|
|
2
|
+
data_get,
|
|
3
|
+
data_set
|
|
4
|
+
} from "./chunk-ZJPKS2MQ.js";
|
|
5
|
+
import {
|
|
6
|
+
diff,
|
|
7
|
+
isEqual
|
|
8
|
+
} from "./chunk-LDSWHSRX.js";
|
|
9
|
+
|
|
10
|
+
// src/obj.ts
|
|
11
|
+
var Objectable = class _Objectable {
|
|
12
|
+
/**
|
|
13
|
+
* Create a new Objectable instance.
|
|
14
|
+
*
|
|
15
|
+
* @param {T} value The initial object value
|
|
16
|
+
*/
|
|
17
|
+
constructor(value) {
|
|
18
|
+
this.value = structuredClone(value);
|
|
19
|
+
this.originalValue = structuredClone(value);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get the current object state.
|
|
23
|
+
*
|
|
24
|
+
* @returns {T} The current object
|
|
25
|
+
*/
|
|
26
|
+
toObject() {
|
|
27
|
+
return this.value;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Alias for toObject().
|
|
31
|
+
*
|
|
32
|
+
* @returns {T} The current object
|
|
33
|
+
*/
|
|
34
|
+
get() {
|
|
35
|
+
return this.value;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get the original state from construction.
|
|
39
|
+
*
|
|
40
|
+
* @returns {T} The original object
|
|
41
|
+
*/
|
|
42
|
+
getOriginal() {
|
|
43
|
+
return this.originalValue;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Sync original state with current state (marking it as clean).
|
|
47
|
+
*
|
|
48
|
+
* @returns {this} The Objectable instance
|
|
49
|
+
*/
|
|
50
|
+
syncOriginal() {
|
|
51
|
+
this.originalValue = structuredClone(this.value);
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Determine if any attribute has been modified.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} [key] Optional key to check specifically
|
|
58
|
+
* @returns {boolean} True if dirty, false otherwise
|
|
59
|
+
*/
|
|
60
|
+
isDirty(key) {
|
|
61
|
+
if (key) {
|
|
62
|
+
return !isEqual(data_get(this.originalValue, key), data_get(this.value, key));
|
|
63
|
+
}
|
|
64
|
+
return !isEqual(this.originalValue, this.value);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Determine if the object is equivalent to its original state.
|
|
68
|
+
*
|
|
69
|
+
* @param {string} [key] Optional key to check specifically
|
|
70
|
+
* @returns {boolean} True if clean, false otherwise
|
|
71
|
+
*/
|
|
72
|
+
isClean(key) {
|
|
73
|
+
return !this.isDirty(key);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get the attributes that have been modified.
|
|
77
|
+
*
|
|
78
|
+
* @returns {Partial<T>} The dirty attributes
|
|
79
|
+
*/
|
|
80
|
+
getDirty() {
|
|
81
|
+
return diff(this.originalValue, this.value);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get a value by dot notation.
|
|
85
|
+
*
|
|
86
|
+
* @param {string} key The key to retrieve
|
|
87
|
+
* @param {unknown} [defaultValue=null] The default value if not found
|
|
88
|
+
* @returns {unknown} The retrieved value
|
|
89
|
+
*/
|
|
90
|
+
dataGet(key, defaultValue = null) {
|
|
91
|
+
return data_get(this.value, key, defaultValue);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Set a value by dot notation.
|
|
95
|
+
*
|
|
96
|
+
* @param {string} key The key to set
|
|
97
|
+
* @param {unknown} value The value to set
|
|
98
|
+
* @returns {this} The Objectable instance
|
|
99
|
+
*/
|
|
100
|
+
dataSet(key, value) {
|
|
101
|
+
data_set(this.value, key, value);
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get only specified keys.
|
|
106
|
+
*
|
|
107
|
+
* @param {K[]} keys The keys to include
|
|
108
|
+
* @returns {Objectable<Pick<T, K>>} A new Objectable instance
|
|
109
|
+
*/
|
|
110
|
+
only(keys) {
|
|
111
|
+
const result = {};
|
|
112
|
+
keys.forEach((key) => {
|
|
113
|
+
const k = key;
|
|
114
|
+
if (k in this.value) {
|
|
115
|
+
result[k] = this.value[k];
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
return new _Objectable(result);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get all keys except specified ones.
|
|
122
|
+
*
|
|
123
|
+
* @param {K[]} keys The keys to exclude
|
|
124
|
+
* @returns {Objectable<Omit<T, K>>} A new Objectable instance
|
|
125
|
+
*/
|
|
126
|
+
except(keys) {
|
|
127
|
+
const result = { ...this.value };
|
|
128
|
+
keys.forEach((key) => {
|
|
129
|
+
const k = key;
|
|
130
|
+
delete result[k];
|
|
131
|
+
});
|
|
132
|
+
return new _Objectable(result);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Map over object entries.
|
|
136
|
+
*
|
|
137
|
+
* @param {Function} callback The callback to execute
|
|
138
|
+
* @returns {Record<string, U>} The resulting object
|
|
139
|
+
*/
|
|
140
|
+
map(callback) {
|
|
141
|
+
const result = {};
|
|
142
|
+
for (const [key, val] of Object.entries(this.value)) {
|
|
143
|
+
result[key] = callback(val, key);
|
|
144
|
+
}
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Filter object entries.
|
|
149
|
+
*
|
|
150
|
+
* @param {Function} callback The callback to execute
|
|
151
|
+
* @returns {this} The Objectable instance
|
|
152
|
+
*/
|
|
153
|
+
filter(callback) {
|
|
154
|
+
const result = {};
|
|
155
|
+
for (const [key, val] of Object.entries(this.value)) {
|
|
156
|
+
if (callback(val, key)) {
|
|
157
|
+
result[key] = val;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
this.value = result;
|
|
161
|
+
return this;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Merge with another object.
|
|
165
|
+
*
|
|
166
|
+
* @param {U} other The object to merge with
|
|
167
|
+
* @returns {Objectable<T & U>} A new Objectable instance
|
|
168
|
+
*/
|
|
169
|
+
merge(other) {
|
|
170
|
+
return new _Objectable({ ...this.value, ...other });
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Deep merge with another object (non-mutating on source).
|
|
174
|
+
*
|
|
175
|
+
* @param {Record<string, unknown>} other The object to deep merge with
|
|
176
|
+
* @returns {this} The Objectable instance
|
|
177
|
+
*/
|
|
178
|
+
mergeDeep(other) {
|
|
179
|
+
const merge = (target, source) => {
|
|
180
|
+
const result = { ...target };
|
|
181
|
+
for (const key of Object.keys(source)) {
|
|
182
|
+
const srcVal = source[key];
|
|
183
|
+
const tgtVal = target[key];
|
|
184
|
+
if (srcVal !== null && "object" === typeof srcVal && !Array.isArray(srcVal) && tgtVal !== null && "object" === typeof tgtVal && !Array.isArray(tgtVal)) {
|
|
185
|
+
result[key] = merge(tgtVal, srcVal);
|
|
186
|
+
} else {
|
|
187
|
+
result[key] = srcVal;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return result;
|
|
191
|
+
};
|
|
192
|
+
this.value = merge(this.value, other);
|
|
193
|
+
return this;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Check if object has key.
|
|
197
|
+
*
|
|
198
|
+
* @param {string} key The key to check
|
|
199
|
+
* @returns {boolean} True if key exists
|
|
200
|
+
*/
|
|
201
|
+
has(key) {
|
|
202
|
+
return key in this.value;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get keys.
|
|
206
|
+
*
|
|
207
|
+
* @returns {string[]} The object keys
|
|
208
|
+
*/
|
|
209
|
+
keys() {
|
|
210
|
+
return Object.keys(this.value);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Get values.
|
|
214
|
+
*
|
|
215
|
+
* @returns {unknown[]} The object values
|
|
216
|
+
*/
|
|
217
|
+
values() {
|
|
218
|
+
return Object.values(this.value);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Clone the object.
|
|
222
|
+
*
|
|
223
|
+
* @returns {Objectable<T>} A new cloned Objectable instance
|
|
224
|
+
*/
|
|
225
|
+
clone() {
|
|
226
|
+
return new _Objectable(structuredClone(this.value));
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Pipe to a callback.
|
|
230
|
+
*
|
|
231
|
+
* @param {Function} callback The callback to execute
|
|
232
|
+
* @returns {U} The result of the callback
|
|
233
|
+
*/
|
|
234
|
+
pipe(callback) {
|
|
235
|
+
return callback(this);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Execute callback if condition is met.
|
|
239
|
+
*
|
|
240
|
+
* @param {boolean | Function} condition The condition to check
|
|
241
|
+
* @param {Function} callback The callback to execute
|
|
242
|
+
* @returns {this} The Objectable instance
|
|
243
|
+
*/
|
|
244
|
+
when(condition, callback) {
|
|
245
|
+
const shouldExecute = "function" === typeof condition ? condition() : condition;
|
|
246
|
+
if (shouldExecute) {
|
|
247
|
+
callback(this);
|
|
248
|
+
}
|
|
249
|
+
return this;
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
var obj = (value) => {
|
|
253
|
+
return new Objectable(value);
|
|
254
|
+
};
|
|
255
|
+
var Obj = {
|
|
256
|
+
/** Create a new Objectable instance */
|
|
257
|
+
of: (value) => new Objectable(value),
|
|
258
|
+
/** Get object keys */
|
|
259
|
+
keys: (value) => Object.keys(value),
|
|
260
|
+
/** Get object values */
|
|
261
|
+
values: (value) => Object.values(value),
|
|
262
|
+
/** Merge objects */
|
|
263
|
+
merge: (target, ...sources) => Object.assign({}, target, ...sources)
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
export {
|
|
267
|
+
Objectable,
|
|
268
|
+
obj,
|
|
269
|
+
Obj
|
|
270
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// src/runtime.ts
|
|
2
|
+
function isRecord(value2) {
|
|
3
|
+
return null !== value2 && "object" === typeof value2 && !Array.isArray(value2);
|
|
4
|
+
}
|
|
5
|
+
var tap = (value2, callback) => {
|
|
6
|
+
callback(value2);
|
|
7
|
+
return value2;
|
|
8
|
+
};
|
|
9
|
+
var when = (condition, onTrue, onFalse) => {
|
|
10
|
+
const shouldExecute = "function" === typeof condition ? condition() : Boolean(condition);
|
|
11
|
+
if (shouldExecute) {
|
|
12
|
+
return onTrue();
|
|
13
|
+
} else if (onFalse) {
|
|
14
|
+
return onFalse();
|
|
15
|
+
}
|
|
16
|
+
return void 0;
|
|
17
|
+
};
|
|
18
|
+
var value = (val) => {
|
|
19
|
+
return "function" === typeof val ? val() : val;
|
|
20
|
+
};
|
|
21
|
+
var data_get = (target, key, defaultValue = null) => {
|
|
22
|
+
if (!isRecord(target) && !Array.isArray(target)) {
|
|
23
|
+
return defaultValue;
|
|
24
|
+
}
|
|
25
|
+
const parts = Array.isArray(key) ? key : key.split(".");
|
|
26
|
+
let result = target;
|
|
27
|
+
for (const part of parts) {
|
|
28
|
+
if (!isRecord(result) && !Array.isArray(result)) {
|
|
29
|
+
return defaultValue;
|
|
30
|
+
}
|
|
31
|
+
if (part in result) {
|
|
32
|
+
result = result[part];
|
|
33
|
+
} else {
|
|
34
|
+
return defaultValue;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
var data_set = (target, key, value2) => {
|
|
40
|
+
if (!isRecord(target) && !Array.isArray(target)) {
|
|
41
|
+
return target;
|
|
42
|
+
}
|
|
43
|
+
const parts = Array.isArray(key) ? key : key.split(".");
|
|
44
|
+
let current = target;
|
|
45
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
46
|
+
const part = parts[i];
|
|
47
|
+
if (!isRecord(current)) {
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
const currentRecord = current;
|
|
51
|
+
if (!(part in currentRecord) || !isRecord(currentRecord[part])) {
|
|
52
|
+
currentRecord[part] = {};
|
|
53
|
+
}
|
|
54
|
+
current = currentRecord[part];
|
|
55
|
+
}
|
|
56
|
+
if (isRecord(current)) {
|
|
57
|
+
;
|
|
58
|
+
current[parts[parts.length - 1]] = value2;
|
|
59
|
+
}
|
|
60
|
+
return target;
|
|
61
|
+
};
|
|
62
|
+
var optional = (value2) => {
|
|
63
|
+
return value2 ?? null;
|
|
64
|
+
};
|
|
65
|
+
var retry = async (times, callback, sleepMilliseconds = 0) => {
|
|
66
|
+
let lastError;
|
|
67
|
+
for (let attempt = 1; attempt <= times; attempt++) {
|
|
68
|
+
try {
|
|
69
|
+
return await callback(attempt);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
72
|
+
if (attempt < times && 0 < sleepMilliseconds) {
|
|
73
|
+
await new Promise((resolve) => setTimeout(resolve, sleepMilliseconds));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
throw lastError ?? new Error(`Retry failed after ${times} attempts`);
|
|
78
|
+
};
|
|
79
|
+
var throw_if = (condition, exception) => {
|
|
80
|
+
if ("function" === typeof condition ? condition() : Boolean(condition)) {
|
|
81
|
+
throw "string" === typeof exception ? new Error(exception) : exception;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var throw_unless = (condition, exception) => {
|
|
85
|
+
if (!("function" === typeof condition ? condition() : Boolean(condition))) {
|
|
86
|
+
throw "string" === typeof exception ? new Error(exception) : exception;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export {
|
|
91
|
+
isRecord,
|
|
92
|
+
tap,
|
|
93
|
+
when,
|
|
94
|
+
value,
|
|
95
|
+
data_get,
|
|
96
|
+
data_set,
|
|
97
|
+
optional,
|
|
98
|
+
retry,
|
|
99
|
+
throw_if,
|
|
100
|
+
throw_unless
|
|
101
|
+
};
|