@cldmv/slothlet 2.4.3 → 2.5.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/dist/slothlet.mjs CHANGED
@@ -23,6 +23,12 @@ import { fileURLToPath, pathToFileURL } from "node:url";
23
23
 
24
24
  import { resolvePathFromCaller } from "@cldmv/slothlet/helpers/resolve-from-caller";
25
25
  import { sanitizePathName } from "@cldmv/slothlet/helpers/sanitize";
26
+ import {
27
+ processModuleForAPI,
28
+ analyzeModule,
29
+ processModuleFromAnalysis,
30
+ getCategoryBuildingDecisions
31
+ } from "@cldmv/slothlet/helpers/api_builder";
26
32
 
27
33
 
28
34
 
@@ -239,9 +245,9 @@ const slothletObject = {
239
245
 
240
246
  if (this.loaded) return this.api;
241
247
  if (this.config.lazy) {
242
- this.api = await this.modes.lazy.create.call(this, apiDir, true, this.config.apiDepth || Infinity, 0);
248
+ this.api = await this.modes.lazy.create.call(this, apiDir, this.config.apiDepth || Infinity, 0);
243
249
  } else {
244
- this.api = await this.modes.eager.create.call(this, apiDir, true, this.config.apiDepth || Infinity, 0);
250
+ this.api = await this.modes.eager.create.call(this, apiDir, this.config.apiDepth || Infinity, 0);
245
251
  }
246
252
  if (this.config.debug) console.log(this.api);
247
253
 
@@ -327,7 +333,7 @@ const slothletObject = {
327
333
  },
328
334
 
329
335
 
330
- _toApiKey(name) {
336
+ _toapiPathKey(name) {
331
337
  return sanitizePathName(name, this.config.sanitize || {});
332
338
 
333
339
  },
@@ -337,165 +343,74 @@ const slothletObject = {
337
343
  const { currentDepth = 0, maxDepth = Infinity, mode = "eager", subdirHandler } = options;
338
344
 
339
345
 
340
- if (this.config.debug) {
341
- console.log(`[DEBUG] _buildCategory called with path: ${categoryPath}, mode: ${mode}`);
342
- }
343
-
344
- const files = await fs.readdir(categoryPath, { withFileTypes: true });
345
- const moduleFiles = files.filter((f) => this._shouldIncludeFile(f));
346
- const categoryName = this._toApiKey(path.basename(categoryPath));
347
- const subDirs = files.filter((e) => e.isDirectory() && !e.name.startsWith("."));
346
+ const { buildCategoryDecisions } = await import("@cldmv/slothlet/helpers/api_builder");
347
+ const decisions = await buildCategoryDecisions(categoryPath, {
348
+ currentDepth,
349
+ maxDepth,
350
+ mode,
351
+ subdirHandler,
352
+ instance: this
353
+ });
348
354
 
349
355
 
350
- if (moduleFiles.length === 1 && subDirs.length === 0) {
351
- const moduleExt = path.extname(moduleFiles[0].name);
352
- const moduleName = this._toApiKey(path.basename(moduleFiles[0].name, moduleExt));
353
- const mod = await this._loadSingleModule(path.join(categoryPath, moduleFiles[0].name));
356
+ if (decisions.type === "single-file") {
357
+ const { singleFile } = decisions;
358
+ const { mod, moduleName } = singleFile;
354
359
 
355
360
 
356
- const functionNameMatchesFolder = typeof mod === "function" && mod.name && mod.name.toLowerCase() === categoryName.toLowerCase();
361
+ if (decisions.shouldFlatten) {
362
+ switch (decisions.flattenType) {
363
+ case "function-folder-match":
364
+ case "default-function":
365
+ try {
366
+ Object.defineProperty(mod, "name", { value: decisions.preferredName, configurable: true });
367
+ } catch {
368
+
369
+ }
370
+ return mod;
357
371
 
358
-
359
- const functionNameMatchesFilename =
360
- typeof mod === "function" &&
361
- mod.name &&
362
- this._toApiKey(mod.name).toLowerCase() === this._toApiKey(moduleName).toLowerCase() &&
363
- mod.name !== this._toApiKey(moduleName);
372
+ case "default-export-flatten":
373
+
374
+ return mod;
364
375
 
365
-
366
-
367
-
368
-
369
-
370
-
371
-
376
+ case "object-auto-flatten":
377
+
378
+ return mod[decisions.preferredName];
372
379
 
373
-
374
- if (moduleName === categoryName && typeof mod === "function") {
375
- try {
376
- Object.defineProperty(mod, "name", { value: categoryName, configurable: true });
377
- } catch {
378
-
379
- }
380
- return mod;
381
- }
380
+ case "parent-level-flatten": {
381
+
382
+ const exportValue = mod[Object.keys(mod).filter((k) => k !== "default")[0]];
383
+ return { [decisions.preferredName]: exportValue };
384
+ }
382
385
 
383
-
384
- if (functionNameMatchesFolder) {
385
- try {
386
-
387
- Object.defineProperty(mod, "name", { value: mod.name, configurable: true });
388
- } catch {
389
-
386
+ case "filename-folder-match-flatten":
387
+
388
+ return mod;
390
389
  }
391
- return mod;
392
390
  }
393
391
 
394
392
 
395
- if (functionNameMatchesFilename) {
396
-
397
-
398
-
399
- return { [mod.name]: mod };
393
+ if (decisions.preferredName && decisions.preferredName !== moduleName) {
394
+ return { [decisions.preferredName]: mod };
400
395
  }
401
396
 
402
397
 
403
-
404
- if (
405
- typeof mod === "function" &&
406
- (!mod.name || mod.name === "default" || mod.__slothletDefault === true)
407
- ) {
408
- try {
409
- Object.defineProperty(mod, "name", { value: categoryName, configurable: true });
410
- } catch {
411
-
412
- }
413
- return mod;
414
- }
415
- if (moduleName === categoryName && mod && typeof mod === "object" && !mod.default) {
416
- return { ...mod };
398
+ if (this.config.debug && moduleName === "nest") {
399
+ console.log(`[DEBUG] Single-file default case for nest: moduleName="${moduleName}" mod keys=[${Object.keys(mod)}]`);
417
400
  }
418
401
  return { [moduleName]: mod };
419
402
  }
420
403
 
421
404
 
422
405
  const categoryModules = {};
406
+ const { categoryName, processedModules, subdirectoryDecisions } = decisions;
423
407
 
424
408
 
425
- const defaultExportFiles = [];
426
- const selfReferentialFiles = new Set();
427
- const rawModuleCache = new Map();
428
-
429
-
430
- for (const file of moduleFiles) {
431
- const moduleExt = path.extname(file.name);
432
- const moduleName = this._toApiKey(path.basename(file.name, moduleExt));
433
- const moduleFilePath = path.resolve(categoryPath, file.name);
434
-
435
-
436
- const rawMod = await import(`file://${moduleFilePath.replace(/\\/g, "/")}`);
437
- rawModuleCache.set(file.name, rawMod);
438
-
439
-
440
- if (rawMod && "default" in rawMod) {
441
-
442
- const isSelfReferential = Object.entries(rawMod).some(([key, value]) => key !== "default" && value === rawMod.default);
443
-
444
- if (this.config.debug) {
445
- console.log(`[DEBUG] _buildCategory: Checking ${file.name} in ${categoryPath}`);
446
- console.log(`[DEBUG] - moduleName: ${moduleName}`);
447
- console.log(`[DEBUG] - has default: ${rawMod && "default" in rawMod}`);
448
- console.log(`[DEBUG] - isSelfReferential: ${isSelfReferential}`);
449
- }
450
-
451
- if (!isSelfReferential) {
452
-
453
- const processedMod = await this._loadSingleModule(path.join(categoryPath, file.name));
454
- defaultExportFiles.push({ file, moduleName, mod: processedMod });
455
- if (this.config.debug) {
456
- console.log(`[DEBUG] Found default export in ${file.name} (non-self-referential)`);
457
- }
458
- } else {
459
- selfReferentialFiles.add(moduleName);
460
- if (this.config.debug) {
461
- console.log(`[DEBUG] Skipped ${file.name} - self-referential default export`);
462
- }
463
- }
464
- }
465
- }
466
-
467
- const hasMultipleDefaultExports = defaultExportFiles.length > 1;
468
-
469
- if (this.config.debug) {
470
- console.log(`[DEBUG] selfReferentialFiles Set:`, Array.from(selfReferentialFiles));
471
- console.log(`[DEBUG] hasMultipleDefaultExports:`, hasMultipleDefaultExports);
472
- }
473
-
474
- for (const file of moduleFiles) {
475
- const moduleExt = path.extname(file.name);
476
- const moduleName = this._toApiKey(path.basename(file.name, moduleExt));
477
-
478
-
479
- if (this.config.debug && moduleName === "config") {
480
- console.log("[DEBUG] Processing config file:", file.name, "moduleName:", moduleName);
481
- console.log("[DEBUG] selfReferentialFiles has config?", selfReferentialFiles.has(moduleName));
482
- }
483
-
409
+ for (const moduleDecision of processedModules) {
410
+ const { moduleName, mod, type, apiPathKey, shouldFlatten, flattenType, specialHandling, processedExports } = moduleDecision;
484
411
 
485
- let mod = null;
486
- const existingDefault = defaultExportFiles.find(def => def.moduleName === moduleName);
487
- if (existingDefault) {
488
- mod = existingDefault.mod;
489
- } else {
412
+ if (specialHandling === "category-merge") {
490
413
 
491
- mod = await this._loadSingleModule(path.join(categoryPath, file.name));
492
- }
493
-
494
- if (this.config.debug && moduleName === "config") {
495
- console.log("[DEBUG] Config mod type:", typeof mod);
496
- console.log("[DEBUG] Config mod keys:", Object.keys(mod));
497
- }
498
- if (moduleName === categoryName && mod && typeof mod === "object") {
499
414
  if (
500
415
  Object.prototype.hasOwnProperty.call(mod, categoryName) &&
501
416
  typeof mod[categoryName] === "object" &&
@@ -503,139 +418,86 @@ const slothletObject = {
503
418
  ) {
504
419
  Object.assign(categoryModules, mod[categoryName]);
505
420
  for (const [key, value] of Object.entries(mod)) {
506
- if (key !== categoryName) categoryModules[this._toApiKey(key)] = value;
421
+ if (key !== categoryName) categoryModules[this._toapiPathKey(key)] = value;
507
422
  }
508
423
  } else {
509
424
  Object.assign(categoryModules, mod);
510
425
  }
511
- } else if (typeof mod === "function") {
426
+ } else if (type === "function") {
512
427
 
513
- const isSelfReferential = selfReferentialFiles.has(moduleName);
514
-
515
-
516
- let apiKey;
517
- if (hasMultipleDefaultExports && mod.__slothletDefault === true && !isSelfReferential) {
518
-
519
- apiKey = moduleName;
428
+ if (specialHandling === "multi-default-filename") {
520
429
  try {
521
430
  Object.defineProperty(mod, "name", { value: moduleName, configurable: true });
522
431
  } catch {
523
432
 
524
433
  }
525
- if (this.config.debug) {
526
- console.log(`[DEBUG] Multi-default detected: using filename '${moduleName}' for default export`);
527
- }
528
- } else if (selfReferentialFiles.has(moduleName)) {
529
-
530
- if (this.config.debug) {
531
- console.log(`[DEBUG] Self-referential default export: treating ${moduleName} as namespace`);
532
- }
533
-
534
- categoryModules[moduleName] = mod[moduleName] || mod;
535
- continue;
434
+ categoryModules[moduleName] = mod;
435
+ } else if (specialHandling === "prefer-function-name") {
436
+ categoryModules[apiPathKey] = mod;
536
437
  } else {
537
438
 
538
- const fnName = mod.name && mod.name !== "default" ? mod.name : moduleName;
539
- try {
540
- Object.defineProperty(mod, "name", { value: fnName, configurable: true });
541
- } catch {
542
-
543
- }
544
-
545
-
546
-
547
- if (fnName && fnName.toLowerCase() === moduleName.toLowerCase() && fnName !== moduleName) {
548
-
549
- apiKey = fnName;
550
- if (this.config.debug) {
551
- console.log(`[DEBUG] Using function name '${fnName}' instead of module name '${moduleName}'`);
552
- }
553
- } else {
554
-
555
- apiKey = this._toApiKey(fnName);
556
- if (this.config.debug) {
557
- console.log(`[DEBUG] Using sanitized key '${apiKey}' for function '${fnName}' (module: '${moduleName}')`);
558
- }
559
- }
439
+ categoryModules[apiPathKey] = mod;
560
440
  }
561
-
562
- categoryModules[apiKey] = mod;
563
- } else {
564
-
565
- let hasPreferredName = false;
566
- const modWithPreferredNames = {};
567
-
568
-
569
-
570
-
571
-
572
-
573
-
574
-
575
-
576
-
577
-
441
+ } else if (type === "self-referential") {
578
442
 
443
+ categoryModules[moduleName] = mod[moduleName] || mod;
444
+ } else if (type === "object") {
579
445
 
580
-
581
-
582
-
583
-
584
-
585
-
586
-
587
-
588
-
589
-
590
-
591
- for (const [exportName, exportValue] of Object.entries(mod)) {
592
- if (
593
- typeof exportValue === "function" &&
594
- exportValue.name &&
595
- this._toApiKey(exportValue.name).toLowerCase() === this._toApiKey(moduleName).toLowerCase() &&
596
- exportValue.name !== this._toApiKey(moduleName)
597
- ) {
598
-
599
- modWithPreferredNames[exportValue.name] = exportValue;
600
- hasPreferredName = true;
601
- if (this.config.debug) {
602
- console.log("[DEBUG] Using preferred name:", exportValue.name, "instead of:", this._toApiKey(moduleName));
446
+ if (specialHandling === "preferred-export-names") {
447
+ Object.assign(categoryModules, processedExports);
448
+ } else if (shouldFlatten) {
449
+ switch (flattenType) {
450
+ case "single-default-object": {
451
+
452
+ const flattened = { ...mod.default };
453
+
454
+ for (const [key, value] of Object.entries(mod)) {
455
+ if (key !== "default") {
456
+ flattened[key] = value;
457
+ }
458
+ }
459
+ categoryModules[apiPathKey] = flattened;
460
+ break;
461
+ }
462
+ case "multi-default-no-default": {
463
+
464
+ const moduleKeys = Object.keys(mod).filter((k) => k !== "default");
465
+ for (const key of moduleKeys) {
466
+ categoryModules[key] = mod[key];
467
+ }
468
+ break;
469
+ }
470
+ case "single-named-export-match":
471
+
472
+ categoryModules[apiPathKey] = mod[apiPathKey];
473
+ break;
474
+ case "category-name-match-flatten": {
475
+
476
+ const moduleKeys = Object.keys(mod).filter((k) => k !== "default");
477
+ for (const key of moduleKeys) {
478
+ categoryModules[key] = mod[key];
479
+ }
480
+ break;
603
481
  }
604
- } else {
605
- modWithPreferredNames[this._toApiKey(exportName)] = exportValue;
606
- }
607
- }
608
-
609
- if (hasPreferredName) {
610
- Object.assign(categoryModules, modWithPreferredNames);
611
-
612
- } else if (selfReferentialFiles.has(moduleName)) {
613
-
614
- if (this.config.debug) {
615
- console.log(`[DEBUG] Self-referential object: treating ${moduleName} as namespace`);
616
482
  }
617
- categoryModules[moduleName] = mod[moduleName] || mod;
618
483
  } else {
619
- categoryModules[this._toApiKey(moduleName)] = mod;
620
-
621
-
622
484
 
485
+ categoryModules[apiPathKey] = mod;
623
486
  }
624
487
  }
625
488
  }
626
489
 
627
490
 
628
- for (const subDirEntry of subDirs) {
629
- if (currentDepth < maxDepth) {
630
- const key = this._toApiKey(subDirEntry.name);
631
- const subDirPath = path.join(categoryPath, subDirEntry.name);
491
+ for (const subDirDecision of subdirectoryDecisions) {
492
+ if (subDirDecision.shouldRecurse) {
493
+ const { name, path: subDirPath, apiPathKey } = subDirDecision;
632
494
  let subModule;
633
495
 
634
496
  if (mode === "lazy" && typeof subdirHandler === "function") {
635
497
  subModule = subdirHandler({
636
- subDirEntry,
498
+ subDirEntry: { name },
637
499
  subDirPath,
638
- key,
500
+ key: apiPathKey,
639
501
  categoryModules,
640
502
  currentDepth,
641
503
  maxDepth
@@ -653,13 +515,13 @@ const slothletObject = {
653
515
  if (
654
516
  typeof subModule === "function" &&
655
517
  subModule.name &&
656
- subModule.name.toLowerCase() === key.toLowerCase() &&
657
- subModule.name !== key
518
+ subModule.name.toLowerCase() === apiPathKey.toLowerCase() &&
519
+ subModule.name !== apiPathKey
658
520
  ) {
659
521
 
660
522
  categoryModules[subModule.name] = subModule;
661
523
  } else {
662
- categoryModules[key] = subModule;
524
+ categoryModules[apiPathKey] = subModule;
663
525
  }
664
526
  }
665
527
  }
@@ -694,164 +556,117 @@ const slothletObject = {
694
556
  },
695
557
 
696
558
 
697
- async _loadSingleModule(modulePath, rootLevel = false) {
698
- const moduleUrl = pathToFileURL(modulePath).href;
699
-
559
+ async _loadSingleModule(modulePath) {
700
560
 
701
- const module = await import(moduleUrl);
561
+ const analysis = await analyzeModule(modulePath, {
562
+ debug: this.config.debug,
563
+ instance: this
564
+ });
565
+ return processModuleFromAnalysis(analysis, {
566
+ debug: this.config.debug,
567
+ instance: this
568
+ });
569
+ },
702
570
 
703
-
704
-
571
+
572
+ async _buildCategoryEnhanced(categoryPath, options = {}) {
573
+ const { currentDepth = 0, maxDepth = Infinity, mode = "eager", subdirHandler } = options;
705
574
 
706
575
 
576
+ const decisions = await getCategoryBuildingDecisions(categoryPath, {
577
+ instance: this,
578
+ currentDepth,
579
+ maxDepth,
580
+ debug: this.config.debug
581
+ });
582
+
583
+ const { processingStrategy, categoryName, processedModules, subDirectories } = decisions;
707
584
 
708
- if (this.config.debug) console.log("module: ", module);
709
585
 
710
- if (typeof module.default === "function") {
711
- let fn;
712
- if (rootLevel) {
713
- fn = module;
714
- } else {
715
- fn = module.default;
716
-
717
- try {
718
- Object.defineProperty(fn, "__slothletDefault", { value: true, enumerable: false });
719
- } catch {
720
-
721
- }
586
+ if (processingStrategy === "single-file" && processedModules.length === 1) {
587
+ const { processedModule, flattening } = processedModules[0];
722
588
 
589
+ if (flattening.shouldFlatten) {
723
590
 
724
-
725
-
726
-
727
-
728
-
729
- for (const [exportName, exportValue] of Object.entries(module)) {
730
- if (exportName !== "default") {
731
-
732
-
733
-
734
-
735
-
736
- fn[this._toApiKey(exportName)] = exportValue;
591
+ if (typeof processedModule === "function") {
592
+ try {
593
+ Object.defineProperty(processedModule, "name", { value: flattening.apiPathKey, configurable: true });
594
+ } catch {
737
595
 
738
596
  }
739
597
  }
740
- if (this.config.debug) console.log("fn: ", fn);
598
+ return processedModule;
741
599
  }
742
- return fn;
600
+
601
+
602
+ return { [flattening.apiPathKey]: processedModule };
743
603
  }
744
604
 
745
- const moduleExports = Object.entries(module);
746
605
 
747
- if (!moduleExports.length) {
748
- throw new Error(
749
- `slothlet: No exports found in module '${modulePath}'. The file is empty or does not export any function/object/variable.`
750
- );
751
- }
752
- if (this.config.debug) console.log("moduleExports: ", moduleExports);
753
-
754
-
755
- const defaultExportObj =
756
- typeof module.default === "object" && module.default !== null
757
- ? module.default
758
- : typeof moduleExports[0][1] === "object" && typeof moduleExports[0][1].default === "function" && moduleExports[0][1] !== null
759
- ? moduleExports[0][1]
760
- : null;
761
- let objectName = null;
762
- if (typeof module.default === "function" && module.default.name) {
763
- objectName = module.default.name;
764
- } else if (moduleExports[0] && moduleExports[0][0] !== "default") {
765
- objectName = moduleExports[0][0];
606
+ const categoryModules = {};
607
+
608
+ for (const { processedModule, flattening } of processedModules) {
609
+ categoryModules[flattening.apiPathKey] = processedModule;
766
610
  }
767
-
768
-
769
611
 
770
- if (this.config.debug) console.log("defaultExportObj: ", defaultExportObj);
771
- if (this.config.debug) console.log("objectName: ", objectName);
612
+
613
+ for (const { dirEntry: subDirEntry, apiPathKey: key } of subDirectories) {
614
+ const subDirPath = path.join(categoryPath, subDirEntry.name);
615
+ let subModule;
772
616
 
773
- if (defaultExportObj && typeof defaultExportObj.default === "function") {
774
- if (this.config.debug) console.log("DEFAULT FUNCTION FOUND FOR: ", module);
775
-
776
- const callableApi = {
777
- [objectName]: function (...args) {
778
- return defaultExportObj.default.apply(defaultExportObj, args);
779
- }
780
- }[objectName];
781
- for (const [methodName, method] of Object.entries(defaultExportObj)) {
782
- if (methodName === "default") continue;
783
- callableApi[methodName] = method;
617
+ if (mode === "lazy" && typeof subdirHandler === "function") {
618
+ subModule = subdirHandler({
619
+ subDirEntry,
620
+ subDirPath,
621
+ key,
622
+ categoryModules,
623
+ currentDepth,
624
+ maxDepth
625
+ });
626
+ } else {
627
+
628
+ subModule = await this._buildCategoryEnhanced(subDirPath, {
629
+ currentDepth: currentDepth + 1,
630
+ maxDepth,
631
+ mode: "eager"
632
+ });
784
633
  }
785
-
786
-
787
-
788
-
789
-
790
- if (this.config.debug) console.log("callableApi", callableApi);
791
- return callableApi;
792
- } else if (defaultExportObj) {
793
- if (this.config.debug) console.log("DEFAULT FOUND FOR: ", module);
794
634
 
795
- const obj = { ...defaultExportObj };
796
-
797
-
798
-
799
-
800
-
801
-
802
635
 
803
-
804
-
805
-
806
-
807
-
808
- for (const [exportName, exportValue] of Object.entries(module)) {
809
- if (exportName !== "default" && exportValue !== obj) {
810
-
811
-
812
-
813
-
814
-
815
- obj[this._toApiKey(exportName)] = exportValue;
816
- }
636
+ if (
637
+ typeof subModule === "function" &&
638
+ subModule.name &&
639
+ subModule.name.toLowerCase() === key.toLowerCase() &&
640
+ subModule.name !== key
641
+ ) {
642
+ categoryModules[subModule.name] = subModule;
643
+ } else {
644
+ categoryModules[key] = subModule;
817
645
  }
818
-
819
- return obj;
820
646
  }
821
-
822
- const namedExports = Object.entries(module).filter(([k]) => k !== "default");
823
- if (this.config.debug) console.log("namedExports: ", namedExports);
824
- if (namedExports.length === 1 && !module.default) {
825
- if (typeof namedExports[0][1] === "object") {
826
-
827
- if (this.config.debug) console.log("namedExports[0][1] === object: ", namedExports[0][1]);
828
- const obj = { ...namedExports[0][1] };
829
-
830
-
831
-
832
-
833
-
834
-
835
-
836
-
837
-
838
647
 
839
- return obj;
840
- }
841
- if (typeof namedExports[0][1] === "function") {
842
- if (this.config.debug) console.log("namedExports[0][1] === function: ", namedExports[0][1]);
843
-
844
-
845
- return namedExports[0][1];
648
+
649
+ const keys = Object.keys(categoryModules);
650
+ if (keys.length === 1) {
651
+ const singleKey = keys[0];
652
+ if (singleKey === categoryName) {
653
+ const single = categoryModules[singleKey];
654
+ if (typeof single === "function") {
655
+ if (single.name !== categoryName) {
656
+ try {
657
+ Object.defineProperty(single, "name", { value: categoryName, configurable: true });
658
+ } catch {
659
+
660
+ }
661
+ }
662
+ return single;
663
+ } else if (single && typeof single === "object" && !Array.isArray(single)) {
664
+ return single;
665
+ }
846
666
  }
847
667
  }
848
- const apiExport = {};
849
- for (const [exportName, exportValue] of namedExports) {
850
-
851
-
852
- apiExport[this._toApiKey(exportName)] = exportValue;
853
- }
854
- return apiExport;
668
+
669
+ return categoryModules;
855
670
  },
856
671
 
857
672