@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 +1 -1
- package/src/lib/Collection.js +31 -25
- package/src/lib/FileObject.js +20 -3
- package/src/types/Collection.d.ts +25 -9
- package/src/types/FileObject.d.ts +23 -0
package/package.json
CHANGED
package/src/lib/Collection.js
CHANGED
|
@@ -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
|
}
|
package/src/lib/FileObject.js
CHANGED
|
@@ -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
|
|
218
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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'
|
|
239
|
+
* // result: { name: ['Alice', 'Bob'], age: [25, 30] }
|
|
237
240
|
* ```
|
|
238
241
|
*/
|
|
239
|
-
static flattenObjectArray(
|
|
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
|
}
|