@gesslar/toolkit 0.2.6 → 0.2.8

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.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Get in, bitches, we're going toolkitting.",
5
5
  "main": "./src/index.js",
6
6
  "type": "module",
@@ -498,31 +498,6 @@ export default class Collection {
498
498
  return result
499
499
  }
500
500
 
501
- static flattenObjectArray(objects) {
502
- const req = "Array"
503
- const type = Data.typeOf(objects)
504
-
505
- Valid.type(objects, req, `Invalid objects array. Expected '${req}', got '${type}'`)
506
-
507
- return objects.reduce((acc, curr) => {
508
- const elemType = Data.typeOf(curr)
509
-
510
- if(!Data.isPlainObject(curr))
511
- throw Sass.new(`Invalid array element. Expected plain object, got '${elemType}'`)
512
-
513
- Valid.prototypePollutionProtection(Object.keys(curr))
514
-
515
- Object.entries(curr).forEach(([key, value]) => {
516
- if(!acc[key])
517
- acc[key] = []
518
-
519
- acc[key].push(value)
520
- })
521
-
522
- return acc
523
- }, {})
524
- }
525
-
526
501
  static trimArray(arr, except=[]) {
527
502
  Valid.type(arr, "Array")
528
503
  Valid.type(except, "Array")
@@ -559,4 +534,35 @@ export default class Collection {
559
534
 
560
535
  return arr
561
536
  }
537
+
538
+ static transposeObjects(objects) {
539
+ const req = "Array"
540
+ const type = Data.typeOf(objects)
541
+
542
+ Valid.type(objects, req, `Invalid objects array. Expected '${req}', got '${type}'`)
543
+
544
+ return objects.reduce((acc, curr) => {
545
+ const elemType = Data.typeOf(curr)
546
+
547
+ if(!Data.isPlainObject(curr))
548
+ throw Sass.new(`Invalid array element. Expected plain object, got '${elemType}'`)
549
+
550
+ Valid.prototypePollutionProtection(Object.keys(curr))
551
+
552
+ Object.entries(curr).forEach(([key, value]) => {
553
+ if(!acc[key])
554
+ acc[key] = []
555
+
556
+ acc[key].push(value)
557
+ })
558
+
559
+ return acc
560
+ }, {})
561
+ }
562
+
563
+ static flattenObjectArray(input) {
564
+ const flattened = Array.isArray(input) ? input.flat() : input
565
+
566
+ return Collection.transposeObjects(flattened)
567
+ }
562
568
  }
@@ -353,12 +353,12 @@ export default class FileObject extends FS {
353
353
  async read(encoding="utf8") {
354
354
  const filePath = this.path
355
355
 
356
- if(!(await this.exists))
357
- throw Sass.new(`No such file '${filePath}'`)
358
-
359
356
  if(!filePath)
360
357
  throw Sass.new("No absolute path in file map")
361
358
 
359
+ if(!(await this.exists))
360
+ throw Sass.new(`No such file '${filePath}'`)
361
+
362
362
  return await fs.readFile(filePath, encoding)
363
363
  }
364
364
 
@@ -409,4 +409,21 @@ export default class FileObject extends FS {
409
409
 
410
410
  throw Sass.new(`Content is neither valid JSON5 nor valid YAML:\n'${this.path}'`)
411
411
  }
412
+
413
+ /**
414
+ * Loads a file as a module and returns it.
415
+ *
416
+ * @returns {Promise<object>} The file contents as a module.
417
+ */
418
+ async import() {
419
+ const fileUri = this.uri
420
+
421
+ if(!fileUri)
422
+ throw Sass.new("No URI in file map")
423
+
424
+ if(!(await this.exists))
425
+ throw Sass.new(`No such file '${fileUri}'`)
426
+
427
+ return await import(fileUri)
428
+ }
412
429
  }
@@ -214,29 +214,45 @@ export default class Collection {
214
214
  static allocateObject(source: Array<unknown>, spec: Array<unknown> | ((source: Array<unknown>) => Promise<Array<unknown>> | Array<unknown>)): Promise<Record<string, unknown>>
215
215
 
216
216
  /**
217
- * Flattens an array of plain objects into a single object where each key contains
218
- * an array of all values for that key across all input objects.
217
+ * Flattens one level of an array of plain objects, transposing values so each
218
+ * key maps to the collected values from every object.
219
219
  *
220
- * @param objects - Array of plain objects to flatten
220
+ * Accepts either a simple array of objects or an array that mixes objects and
221
+ * nested object arrays (one level deep). Nested arrays are flattened before
222
+ * transposition.
223
+ *
224
+ * @param input - Array of plain objects (optionally containing nested arrays)
221
225
  * @returns Object with keys mapped to arrays of values from all input objects
222
226
  *
223
- * @throws {Sass} If objects is not an Array or if any element is not a plain object
227
+ * @throws {Sass} If input is not an Array or if any element is not a plain object after flattening
224
228
  *
225
229
  * @example
226
230
  * ```typescript
227
231
  * import { Collection } from '@gesslar/toolkit'
228
232
  *
229
233
  * const objects = [
230
- * { name: 'Alice', age: 25 },
231
- * { name: 'Bob', age: 30 },
232
- * { name: 'Charlie', age: 35 }
234
+ * [{ name: 'Alice', age: 25 }],
235
+ * { name: 'Bob', age: 30 }
233
236
  * ]
234
237
  *
235
238
  * const result = Collection.flattenObjectArray(objects)
236
- * // result: { name: ['Alice', 'Bob', 'Charlie'], age: [25, 30, 35] }
239
+ * // result: { name: ['Alice', 'Bob'], age: [25, 30] }
237
240
  * ```
238
241
  */
239
- static flattenObjectArray(objects: Array<Record<string, unknown>>): Record<string, Array<unknown>>
242
+ static flattenObjectArray(
243
+ input: Array<Record<string, unknown> | Array<Record<string, unknown>>>
244
+ ): Record<string, Array<unknown>>
245
+
246
+ /**
247
+ * Transposes an array of plain objects into an object of arrays, keyed by the
248
+ * original object keys.
249
+ *
250
+ * @param objects - Array of plain objects to transpose
251
+ * @returns Object with keys mapped to arrays of values from the input objects
252
+ *
253
+ * @throws {Sass} If objects is not an Array or if any element is not a plain object
254
+ */
255
+ static transposeObjects(objects: Array<Record<string, unknown>>): Record<string, Array<unknown>>
240
256
 
241
257
  /**
242
258
  * Trims falsy values from both ends of an array.
@@ -326,4 +326,27 @@ export default class FileObject extends FS {
326
326
 
327
327
  /** Load an object from JSON5 or YAML file with type specification */
328
328
  loadData(type?: 'json' | 'json5' | 'yaml' | 'any', encoding?: string): Promise<unknown>
329
+
330
+ /**
331
+ * Dynamically import the file using the resolved file URI.
332
+ *
333
+ * Uses Node.js' native dynamic `import()` under the hood, allowing consumers to load
334
+ * ESM modules from disk with full path resolution handled by FileObject. The method
335
+ * verifies the file exists before attempting the import to provide clearer error
336
+ * messaging and prevent low-level loader failures.
337
+ *
338
+ * @typeParam TModule - Expected module shape. Defaults to a loose record to help with
339
+ * module namespace typing.
340
+ *
341
+ * @returns The imported module namespace object.
342
+ *
343
+ * @throws {Error} When the file does not exist or the path cannot be converted to a URI.
344
+ *
345
+ * @example
346
+ * ```typescript
347
+ * const configModule = await file.import<{ default: Config }>()
348
+ * const config = configModule.default
349
+ * ```
350
+ */
351
+ import<TModule = Record<string, unknown>>(): Promise<TModule>
329
352
  }