@gesslar/toolkit 0.1.3 → 0.1.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gesslar/toolkit",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Get in, bitches, we're going toolkitting.",
5
5
  "main": "./src/index.js",
6
6
  "type": "module",
package/src/lib/Data.js CHANGED
@@ -273,9 +273,9 @@ export default class Data {
273
273
  * @returns {Promise<object>} The mapped object
274
274
  */
275
275
  static async mapObject(original, transformer, mutate = false) {
276
- Valid.validType(original, "object", {allowEmpty: true})
277
- Valid.validType(transformer, "function")
278
- Valid.validType(mutate, "boolean")
276
+ Valid.type(original, "object", {allowEmpty: true})
277
+ Valid.type(transformer, "function")
278
+ Valid.type(mutate, "boolean")
279
279
 
280
280
  const result = mutate ? original : {}
281
281
 
@@ -565,4 +565,45 @@ export default class Data {
565
565
  static clamped(val, min, max) {
566
566
  return val >= min && val <= max
567
567
  }
568
+
569
+ /**
570
+ * Checks if a value is a plain object - created with object literals {},
571
+ * new Object(), or Object.create(null).
572
+ *
573
+ * Distinguishes plain objects from objects created by custom constructors, built-ins,
574
+ * or primitives. Plain objects only have Object.prototype or null in their prototype chain.
575
+ *
576
+ * @param {unknown} value - The value to check
577
+ * @returns {boolean} True if the value is a plain object, false otherwise
578
+ *
579
+ * @example
580
+ * isPlainObject({}) // true
581
+ * isPlainObject(new Object()) // true
582
+ * isPlainObject(Object.create(null)) // true
583
+ * isPlainObject([]) // false
584
+ * isPlainObject(new Date()) // false
585
+ * isPlainObject(null) // false
586
+ * isPlainObject("string") // false
587
+ * isPlainObject(class Person{}) // false
588
+ */
589
+ static isPlainObject(value) {
590
+ // First, check if it's an object and not null
591
+ if(typeof value !== "object" || value === null)
592
+ return false
593
+
594
+ // If it has no prototype, it's plain (created with Object.create(null))
595
+ const proto = Object.getPrototypeOf(value)
596
+
597
+ if(proto === null)
598
+ return true
599
+
600
+ // Check if the prototype chain ends at Object.prototype
601
+ // This handles objects created with {} or new Object()
602
+ let current = proto
603
+
604
+ while(Object.getPrototypeOf(current) !== null)
605
+ current = Object.getPrototypeOf(current)
606
+
607
+ return proto === current
608
+ }
568
609
  }
package/src/lib/Valid.js CHANGED
@@ -5,14 +5,13 @@ import Data from "./Data.js"
5
5
 
6
6
  export default class Valid {
7
7
  /**
8
- * Validates a value against a type
8
+ * Validates a value against a type. Uses Data.isType.
9
9
  *
10
10
  * @param {unknown} value - The value to validate
11
- * @param {string} type - The expected type in the form of "object",
12
- * "object[]", "object|object[]"
11
+ * @param {string} type - The expected type in the form of "object", "object[]", "object|object[]"
13
12
  * @param {object} [options] - Additional options for validation.
14
13
  */
15
- static validType(value, type, options) {
14
+ static type(value, type, options) {
16
15
  Valid.assert(
17
16
  Data.isType(value, type, options),
18
17
  `Invalid type. Expected ${type}, got ${JSON.stringify(value)}`,
@@ -248,4 +248,43 @@ export default class Data {
248
248
 
249
249
  /** Checks if a value is within a specified range (inclusive) */
250
250
  static clamped(val: number, min: number, max: number): boolean
251
+
252
+ /**
253
+ * Checks if a value is a plain object - created with object literals {},
254
+ * new Object(), or Object.create(null).
255
+ *
256
+ * Distinguishes plain objects from objects created by custom constructors, built-ins,
257
+ * or primitives. Plain objects only have Object.prototype or null in their prototype chain.
258
+ * Useful for validating configuration objects or data structures that should be plain objects.
259
+ *
260
+ * @param value - The value to check for plain object status
261
+ * @returns True if the value is a plain object, false otherwise
262
+ *
263
+ * @example
264
+ * ```typescript
265
+ * import { Data } from '@gesslar/toolkit'
266
+ *
267
+ * // Plain objects return true
268
+ * console.log(Data.isPlainObject({})) // true
269
+ * console.log(Data.isPlainObject(new Object())) // true
270
+ * console.log(Data.isPlainObject(Object.create(null))) // true
271
+ *
272
+ * // Non-plain objects return false
273
+ * console.log(Data.isPlainObject([])) // false
274
+ * console.log(Data.isPlainObject(new Date())) // false
275
+ * console.log(Data.isPlainObject(/regex/)) // false
276
+ * console.log(Data.isPlainObject(null)) // false
277
+ * console.log(Data.isPlainObject('string')) // false
278
+ *
279
+ * // Useful for validating config objects
280
+ * function processConfig(config: unknown) {
281
+ * if (!Data.isPlainObject(config)) {
282
+ * throw new Error('Config must be a plain object')
283
+ * }
284
+ * // Safe to treat as object with string keys
285
+ * return Object.entries(config)
286
+ * }
287
+ * ```
288
+ */
289
+ static isPlainObject(value: unknown): boolean
251
290
  }
@@ -3,8 +3,8 @@
3
3
 
4
4
  export default class Valid {
5
5
  /** Validate a value against a type specification */
6
- static validType(value: unknown, type: string, options?: { allowEmpty?: boolean }): void
6
+ static type(value: unknown, type: string, options?: { allowEmpty?: boolean }): void
7
7
 
8
8
  /** Assert a condition */
9
9
  static assert(condition: boolean, message: string, arg?: number | null): void
10
- }
10
+ }