@cldmv/slothlet 2.3.2 → 2.4.1

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.
@@ -38,23 +38,88 @@ export async function create(dir, rootLevel = true, maxDepth = Infinity, current
38
38
  let rootDefaultFunction = null;
39
39
 
40
40
  if (rootLevel) {
41
- for (const entry of entries) {
42
- if (this._shouldIncludeFile(entry)) {
43
- const ext = path.extname(entry.name);
44
- const fileName = path.basename(entry.name, ext);
45
- const apiKey = this._toApiKey(fileName);
46
- const mod = await this._loadSingleModule(path.join(dir, entry.name), true);
47
- if (mod && typeof mod.default === "function") {
48
- if (!rootDefaultFunction) rootDefaultFunction = mod.default;
41
+
42
+ const moduleFiles = entries.filter((e) => this._shouldIncludeFile(e));
43
+ const defaultExportFiles = [];
44
+
45
+
46
+ for (const entry of moduleFiles) {
47
+ const ext = path.extname(entry.name);
48
+ const fileName = path.basename(entry.name, ext);
49
+ const mod = await this._loadSingleModule(path.join(dir, entry.name), true);
50
+
51
+ if (this.config.debug) {
52
+ console.log(`[DEBUG] First pass - ${fileName}: hasDefault=${mod && "default" in mod}`);
53
+ }
54
+
55
+ if (mod && "default" in mod) {
56
+ defaultExportFiles.push({ entry, fileName, mod });
57
+ if (this.config.debug) {
58
+ console.log(`[DEBUG] Added ${fileName} to defaultExportFiles`);
59
+ }
60
+ }
61
+ }
62
+ const hasMultipleDefaultExports = defaultExportFiles.length > 1;
63
+
64
+ if (this.config.debug) {
65
+ console.log(
66
+ `[DEBUG] Detection result: ${defaultExportFiles.length} default exports found, hasMultipleDefaultExports=${hasMultipleDefaultExports}`
67
+ );
68
+ console.log(
69
+ `[DEBUG] Default export files:`,
70
+ defaultExportFiles.map((f) => f.fileName)
71
+ );
72
+ }
73
+
74
+
75
+ for (const entry of moduleFiles) {
76
+ const ext = path.extname(entry.name);
77
+ const fileName = path.basename(entry.name, ext);
78
+ const apiKey = this._toApiKey(fileName);
79
+ const mod = await this._loadSingleModule(path.join(dir, entry.name), true);
80
+
81
+ if (mod && typeof mod.default === "function") {
82
+ if (hasMultipleDefaultExports) {
83
+
84
+ api[apiKey] = mod.default;
85
+
86
+
49
87
  for (const [key, value] of Object.entries(mod)) {
50
- if (key !== "default") api[key] = value;
88
+ if (key !== "default") {
89
+ api[apiKey][key] = value;
90
+ }
91
+ }
92
+
93
+ if (this.config.debug) {
94
+ console.log(`[DEBUG] Multi-default in eager mode: using filename '${apiKey}' for default export`);
51
95
  }
52
96
  } else {
53
- api[apiKey] = mod;
97
+
98
+
99
+ if (this.config.debug) {
100
+ console.log(
101
+ `[DEBUG] Processing traditional default: hasMultipleDefaultExports=${hasMultipleDefaultExports}, rootDefaultFunction=${!!rootDefaultFunction}`
102
+ );
103
+ }
104
+ if (!hasMultipleDefaultExports && !rootDefaultFunction) {
105
+ rootDefaultFunction = mod.default;
106
+ if (this.config.debug) {
107
+ console.log(`[DEBUG] Set rootDefaultFunction to:`, mod.default.name);
108
+ }
109
+ } else {
110
+ if (this.config.debug) {
111
+ console.log(`[DEBUG] Skipped setting rootDefaultFunction due to multi-default scenario`);
112
+ }
113
+ }
54
114
  for (const [key, value] of Object.entries(mod)) {
55
- rootNamedExports[key] = value;
115
+ if (key !== "default") api[key] = value;
56
116
  }
57
117
  }
118
+ } else {
119
+ api[apiKey] = mod;
120
+ for (const [key, value] of Object.entries(mod)) {
121
+ rootNamedExports[key] = value;
122
+ }
58
123
  }
59
124
  }
60
125
  }
@@ -67,11 +132,21 @@ export async function create(dir, rootLevel = true, maxDepth = Infinity, current
67
132
  }
68
133
 
69
134
  let finalApi;
135
+ if (this.config.debug) {
136
+ console.log(`[DEBUG] Final assembly: rootDefaultFunction=${!!rootDefaultFunction}`);
137
+ console.log(`[DEBUG] API object keys before final assembly:`, Object.keys(api));
138
+ }
70
139
  if (rootDefaultFunction) {
71
140
  Object.assign(rootDefaultFunction, api);
72
141
  finalApi = rootDefaultFunction;
142
+ if (this.config.debug) {
143
+ console.log(`[DEBUG] Applied root contributor pattern - final API is function`);
144
+ }
73
145
  } else {
74
146
  finalApi = api;
147
+ if (this.config.debug) {
148
+ console.log(`[DEBUG] No root function - final API is object`);
149
+ }
75
150
  }
76
151
 
77
152
 
@@ -30,20 +30,57 @@ export async function create(dir, rootLevel = true, maxDepth = Infinity, current
30
30
 
31
31
 
32
32
  if (rootLevel) {
33
- for (const entry of entries) {
34
- if (instance._shouldIncludeFile(entry)) {
35
- const ext = path.extname(entry.name);
36
- const fileName = path.basename(entry.name, ext);
37
- const apiKey = instance._toApiKey(fileName);
38
- const mod = await instance._loadSingleModule(path.join(dir, entry.name), true);
39
- if (mod && typeof mod.default === "function") {
40
- if (!rootDefaultFn) rootDefaultFn = mod.default;
33
+
34
+ const moduleFiles = entries.filter((e) => instance._shouldIncludeFile(e));
35
+ const defaultExportFiles = [];
36
+
37
+
38
+ for (const entry of moduleFiles) {
39
+ const ext = path.extname(entry.name);
40
+ const fileName = path.basename(entry.name, ext);
41
+ const mod = await instance._loadSingleModule(path.join(dir, entry.name), true);
42
+
43
+ if (mod && "default" in mod) {
44
+ defaultExportFiles.push({ entry, fileName, mod });
45
+ }
46
+ }
47
+
48
+ const hasMultipleDefaultExports = defaultExportFiles.length > 1;
49
+
50
+
51
+ for (const entry of moduleFiles) {
52
+ const ext = path.extname(entry.name);
53
+ const fileName = path.basename(entry.name, ext);
54
+ const apiKey = instance._toApiKey(fileName);
55
+ const mod = await instance._loadSingleModule(path.join(dir, entry.name), true);
56
+
57
+ if (mod && typeof mod.default === "function") {
58
+ if (hasMultipleDefaultExports) {
59
+
60
+ api[apiKey] = mod.default;
61
+
62
+
63
+ for (const [key, value] of Object.entries(mod)) {
64
+ if (key !== "default") {
65
+ api[apiKey][key] = value;
66
+ }
67
+ }
68
+
69
+ if (instance.config.debug) {
70
+ console.log(`[DEBUG] Multi-default in lazy mode: using filename '${apiKey}' for default export`);
71
+ }
72
+ } else {
73
+
74
+
75
+ if (!hasMultipleDefaultExports && !rootDefaultFn) {
76
+ rootDefaultFn = mod.default;
77
+ }
41
78
  for (const [k, v] of Object.entries(mod)) {
42
79
  if (k !== "default") api[k] = v;
43
80
  }
44
- } else {
45
- api[apiKey] = mod;
46
81
  }
82
+ } else {
83
+ api[apiKey] = mod;
47
84
  }
48
85
  }
49
86
  }
package/dist/slothlet.mjs CHANGED
@@ -420,6 +420,26 @@ const slothletObject = {
420
420
 
421
421
 
422
422
  const categoryModules = {};
423
+
424
+
425
+ const defaultExportFiles = [];
426
+ for (const file of moduleFiles) {
427
+ const moduleExt = path.extname(file.name);
428
+ const moduleName = this._toApiKey(path.basename(file.name, moduleExt));
429
+ const tempMod = await this._loadSingleModule(path.join(categoryPath, file.name));
430
+
431
+
432
+
433
+ if (tempMod && tempMod.__slothletDefault === true) {
434
+ defaultExportFiles.push({ file, moduleName, mod: tempMod });
435
+ if (this.config.debug) {
436
+ console.log(`[DEBUG] Found default export in ${file.name}`);
437
+ }
438
+ }
439
+ }
440
+
441
+ const hasMultipleDefaultExports = defaultExportFiles.length > 1;
442
+
423
443
  for (const file of moduleFiles) {
424
444
  const moduleExt = path.extname(file.name);
425
445
  const moduleName = this._toApiKey(path.basename(file.name, moduleExt));
@@ -444,27 +464,42 @@ const slothletObject = {
444
464
  Object.assign(categoryModules, mod);
445
465
  }
446
466
  } else if (typeof mod === "function") {
447
- const fnName = mod.name && mod.name !== "default" ? mod.name : moduleName;
448
- try {
449
- Object.defineProperty(mod, "name", { value: fnName, configurable: true });
450
- } catch {
451
-
452
- }
453
-
454
-
455
467
 
456
468
  let apiKey;
457
- if (fnName && fnName.toLowerCase() === moduleName.toLowerCase() && fnName !== moduleName) {
469
+ if (hasMultipleDefaultExports && mod.__slothletDefault === true) {
458
470
 
459
- apiKey = fnName;
471
+ apiKey = moduleName;
472
+ try {
473
+ Object.defineProperty(mod, "name", { value: moduleName, configurable: true });
474
+ } catch {
475
+
476
+ }
460
477
  if (this.config.debug) {
461
- console.log(`[DEBUG] Using function name '${fnName}' instead of module name '${moduleName}'`);
478
+ console.log(`[DEBUG] Multi-default detected: using filename '${moduleName}' for default export`);
462
479
  }
463
480
  } else {
464
481
 
465
- apiKey = this._toApiKey(fnName);
466
- if (this.config.debug) {
467
- console.log(`[DEBUG] Using sanitized key '${apiKey}' for function '${fnName}' (module: '${moduleName}')`);
482
+ const fnName = mod.name && mod.name !== "default" ? mod.name : moduleName;
483
+ try {
484
+ Object.defineProperty(mod, "name", { value: fnName, configurable: true });
485
+ } catch {
486
+
487
+ }
488
+
489
+
490
+
491
+ if (fnName && fnName.toLowerCase() === moduleName.toLowerCase() && fnName !== moduleName) {
492
+
493
+ apiKey = fnName;
494
+ if (this.config.debug) {
495
+ console.log(`[DEBUG] Using function name '${fnName}' instead of module name '${moduleName}'`);
496
+ }
497
+ } else {
498
+
499
+ apiKey = this._toApiKey(fnName);
500
+ if (this.config.debug) {
501
+ console.log(`[DEBUG] Using sanitized key '${apiKey}' for function '${fnName}' (module: '${moduleName}')`);
502
+ }
468
503
  }
469
504
  }
470
505
 
@@ -587,6 +622,7 @@ const slothletObject = {
587
622
  }
588
623
  }
589
624
  }
625
+
590
626
  return categoryModules;
591
627
  },
592
628
 
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@cldmv/slothlet",
3
- "version": "2.3.2",
3
+ "version": "2.4.1",
4
4
  "moduleVersions": {
5
- "lazy": "1.0.0",
6
- "eager": "1.0.0"
5
+ "lazy": "1.1.0",
6
+ "eager": "1.1.0"
7
7
  },
8
8
  "description": "Slothlet: Modular API Loader for Node.js. Lazy mode dynamically loads API modules and submodules only when accessed, supporting both lazy and eager loading.",
9
9
  "main": "./index.cjs",
@@ -1 +1 @@
1
- {"version":3,"file":"slothlet_eager.d.mts","sourceRoot":"","sources":["../../../../dist/lib/modes/slothlet_eager.mjs"],"names":[],"mappings":"AA2IA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAsDH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,4BAtBW,MAAM,cACN,OAAO,aACP,MAAM,iBACN,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAqE3B"}
1
+ {"version":3,"file":"slothlet_eager.d.mts","sourceRoot":"","sources":["../../../../dist/lib/modes/slothlet_eager.mjs"],"names":[],"mappings":"AA2IA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAsDH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,4BAtBW,MAAM,cACN,OAAO,aACP,MAAM,iBACN,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAgJ3B"}
@@ -1 +1 @@
1
- {"version":3,"file":"slothlet_lazy.d.mts","sourceRoot":"","sources":["../../../../dist/lib/modes/slothlet_lazy.mjs"],"names":[],"mappings":"AA6JA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,4BAvBW,MAAM,cACN,OAAO,aACP,MAAM,iBACN,MAAM,GACJ,OAAO,CAAC,WAAS,MAAM,CAAC,CAwEpC"}
1
+ {"version":3,"file":"slothlet_lazy.d.mts","sourceRoot":"","sources":["../../../../dist/lib/modes/slothlet_lazy.mjs"],"names":[],"mappings":"AA6JA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,4BAvBW,MAAM,cACN,OAAO,aACP,MAAM,iBACN,MAAM,GACJ,OAAO,CAAC,WAAS,MAAM,CAAC,CA6GpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"slothlet.d.mts","sourceRoot":"","sources":["../../dist/slothlet.mjs"],"names":[],"mappings":"AA04CA;;;;;;;;;GASG;AACH,kDARW,WAAS,MAAM,UACf,WAAS,MAAM,QAwCzB;AAryCD;;;;;;;GAOG;AACH,mBAJU,MAAM,CAIO;AAEvB;;;;;GAKG;AACH,sBAJU,MAAM,CAIU;AAE1B;;;;;GAKG;AACH,wBAJU,MAAM,CAIY;;;;;;;;;UAwxCd,MAAM;;;;;;WAIN,OAAO;;;;;;;eAGP,MAAM;;;;;;;;YAIN,OAAO;;;;;;;;WAKP,MAAM;;;;;;;eAKN,MAAM;;;;;;cAIN,MAAM;;;;;;gBAGN,MAAM;;;;;;eAMjB;QAA8B,UAAU,GAA7B,OAAO;QACY,gBAAgB,GAAnC,OAAO;QACY,gBAAgB,GAAnC,OAAO;QACW,KAAK,GAClC;YAAqC,KAAK,GAA/B,MAAM,EAAE;YACkB,gBAAgB,GAA1C,MAAM,EAAE;YACkB,KAAK,GAA/B,MAAM,EAAE;YACkB,KAAK,GAA/B,MAAM,EAAE;SACrB;KAAA;;AAh0CD;;;;;;;;GAQG;AACH,mCAJW,eAAe,GACb,OAAO,CAAC,WAAS,MAAM,CAAC,CAiCpC"}
1
+ {"version":3,"file":"slothlet.d.mts","sourceRoot":"","sources":["../../dist/slothlet.mjs"],"names":[],"mappings":"AA86CA;;;;;;;;;GASG;AACH,kDARW,WAAS,MAAM,UACf,WAAS,MAAM,QAwCzB;AAz0CD;;;;;;;GAOG;AACH,mBAJU,MAAM,CAIO;AAEvB;;;;;GAKG;AACH,sBAJU,MAAM,CAIU;AAE1B;;;;;GAKG;AACH,wBAJU,MAAM,CAIY;;;;;;;;;UA4zCd,MAAM;;;;;;WAIN,OAAO;;;;;;;eAGP,MAAM;;;;;;;;YAIN,OAAO;;;;;;;;WAKP,MAAM;;;;;;;eAKN,MAAM;;;;;;cAIN,MAAM;;;;;;gBAGN,MAAM;;;;;;eAMjB;QAA8B,UAAU,GAA7B,OAAO;QACY,gBAAgB,GAAnC,OAAO;QACY,gBAAgB,GAAnC,OAAO;QACW,KAAK,GAClC;YAAqC,KAAK,GAA/B,MAAM,EAAE;YACkB,gBAAgB,GAA1C,MAAM,EAAE;YACkB,KAAK,GAA/B,MAAM,EAAE;YACkB,KAAK,GAA/B,MAAM,EAAE;SACrB;KAAA;;AAp2CD;;;;;;;;GAQG;AACH,mCAJW,eAAe,GACb,OAAO,CAAC,WAAS,MAAM,CAAC,CAiCpC"}