@cldmv/slothlet 2.4.2 → 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/README.md CHANGED
@@ -96,7 +96,7 @@ v2.0 represents a ground-up rewrite with enterprise-grade features:
96
96
  ### 🔧 **Smart API Management**
97
97
 
98
98
  - **Callable Interface**: Use `slothlet(options)` for direct API creation
99
- - **Automatic Flattening**: Single-file modules become direct API properties (`math/math.mjs` → `api.math`)
99
+ - **Smart Flattening**: Intelligent rules create clean APIs (`math/math.mjs` → `api.math`, `connection.mjs` → `api.connect()`)
100
100
  - **Intelligent Naming**: Dash-separated names convert automatically (`root-math.mjs` → `api.rootMath`)
101
101
  - **Function Name Preservation**: Maintains original capitalization (`auto-ip.mjs` with `autoIP` → `api.autoIP`)
102
102
  - **Hybrid Exports**: Support for callable APIs with methods, default + named exports, and mixed patterns
@@ -621,12 +621,12 @@ rootstring.mjs → api.rootstring
621
621
  config.mjs → api.config
622
622
  ```
623
623
 
624
- ### Single-File Modules
624
+ ### Filename-Folder Matching Modules
625
625
 
626
626
  ```text
627
- math/math.mjs → api.math (automatic flattening)
628
- string/string.mjs → api.string
629
- util/util.cjs → api.util (CJS support)
627
+ math/math.mjs → api.math (filename matches folder)
628
+ string/string.mjs → api.string (filename matches folder)
629
+ util/util.cjs → api.util (CJS support with filename matching)
630
630
  ```
631
631
 
632
632
  ### Multi-File Modules
@@ -694,6 +694,127 @@ util/parseJSON.mjs → api.util.parseJSON (preserves JSON casing)
694
694
  api/getHTTPStatus.mjs → api.api.getHTTPStatus (preserves HTTP casing)
695
695
  ```
696
696
 
697
+ ## 🏗️ API Flattening Rules
698
+
699
+ Slothlet uses intelligent flattening rules to create clean, intuitive API structures. Understanding these rules helps you organize your modules for the best developer experience:
700
+
701
+ ### 1. **Filename-Folder Matching** (Single Named Export)
702
+
703
+ **When:** A file exports a single named export that matches the sanitized filename
704
+ **Why:** Avoids redundant nesting (`api.math.math.add()` → `api.math.add()`)
705
+ **Reasoning:** When file purpose matches folder purpose, eliminate the duplicate layer
706
+
707
+ ```text
708
+ math/math.mjs (exports { math: {...} }) → api.math (flattened)
709
+ string/string.mjs (exports { string: {...} }) → api.string (flattened)
710
+ util/util.mjs (exports { util: {...} }) → api.util (flattened)
711
+ ```
712
+
713
+ ### 2. **No Default Export + Only Named Exports** ⭐ NEW
714
+
715
+ **When:** A file has **no default export** and **only named exports**
716
+ **Why:** The file acts as a pure function collection, not a module with a main export
717
+ **Reasoning:** If there's no "main thing" (default export), treat all functions as equals at the root level
718
+
719
+ ```text
720
+ connection.mjs (exports { connect, disconnect, isConnected })
721
+ → api.connect(), api.disconnect(), api.isConnected()
722
+ Because: No default export = no main "connection" object needed
723
+
724
+ app.mjs (exports { getAllApps, getCurrentApp, setApp })
725
+ → api.getAllApps(), api.getCurrentApp(), api.setApp()
726
+ Because: No default export = these are standalone utility functions
727
+
728
+ state.mjs (exports { cloneState, emitLog, reset, update })
729
+ → api.cloneState(), api.emitLog(), api.reset(), api.update()
730
+ Because: No default export = treat as individual state utilities
731
+ ```
732
+
733
+ ### 3. **Has Default Export** (Namespace Preservation)
734
+
735
+ **When:** A file has a default export (with or without named exports)
736
+ **Why:** The default export indicates there's a "main thing" that should be the namespace
737
+ **Reasoning:** Default export signals intentional module structure that should be preserved
738
+
739
+ ```text
740
+ config.mjs (exports default + named exports) → api.config.*
741
+ Because: Default export indicates a main config object with methods
742
+
743
+ input.mjs (exports default + named exports) → api.input.*
744
+ Because: Default export indicates a main input handler with utilities
745
+
746
+ volume.mjs (exports default + named exports) → api.volume.*
747
+ Because: Default export indicates a main volume controller with methods
748
+ ```
749
+
750
+ ### 4. **Root-Level Special Cases**
751
+
752
+ **When:** Files are at the root directory level (not in subfolders)
753
+ **Why:** Prevents accidental API pollution and maintains clear root structure
754
+ **Reasoning:** Root files are explicitly placed there and should maintain their intended naming
755
+
756
+ ```text
757
+ root-math.mjs → api.rootMath (namespace preserved)
758
+ Because: Explicitly named "root-math" = keep as intended namespace
759
+
760
+ rootstring.mjs → api.rootstring (namespace preserved)
761
+ Because: Root-level placement = developer wants this specific API structure
762
+
763
+ config.mjs → api.config (namespace preserved)
764
+ Because: Root config file = keep as clear config namespace, don't flatten
765
+ ```
766
+
767
+ ### 5. **Self-Referential Prevention**
768
+
769
+ **When:** A file would create circular/redundant nesting (`api.config.config`)
770
+ **Why:** Prevents infinite nesting and maintains clean API structure
771
+ **Reasoning:** When file/folder names match, assume they represent the same logical concept
772
+
773
+ ```text
774
+ config/config.mjs → api.config (prevented: api.config.config.config...)
775
+ Because: config.mjs in config/ folder = same concept, use folder name only
776
+ ```
777
+
778
+ ### 🎯 Flattening Decision Tree
779
+
780
+ ```mermaid
781
+ flowchart TD
782
+ FILE[Module File] --> ROOT{Root Level?}
783
+
784
+ ROOT -->|Yes| PRESERVE[Preserve Namespace<br/>api.rootMath, api.config]
785
+
786
+ ROOT -->|No| SELFREFER{Self-Referential?}
787
+ SELFREFER -->|Yes| NAMESPACE[Use Namespace<br/>api.config]
788
+
789
+ SELFREFER -->|No| HASDEFAULT{Has Default Export?}
790
+ HASDEFAULT -->|Yes| NAMESPACE
791
+
792
+ HASDEFAULT -->|No| NAMEDONLY{Only Named Exports?}
793
+ NAMEDONLY -->|Yes| FLATTEN[Flatten All Named Exports<br/>api.connect(), api.disconnect()]
794
+
795
+ NAMEDONLY -->|No| SINGLENAMED{Single Named Export<br/>Matching Filename?}
796
+ SINGLENAMED -->|Yes| FLATTENSINGLE[Flatten Single Export<br/>api.math]
797
+ SINGLENAMED -->|No| NAMESPACE
798
+
799
+ style FLATTEN fill:#e1f5fe
800
+ style FLATTENSINGLE fill:#e8f5e8
801
+ style NAMESPACE fill:#fff3e0
802
+ style PRESERVE fill:#fce4ec
803
+ ```
804
+
805
+ ### 🚀 Benefits of Smart Flattening
806
+
807
+ - **Cleaner APIs**: `api.connect()` instead of `api.connection.connect()`
808
+ _Why it matters:_ Reduces typing, improves readability, and matches how you'd naturally call connection functions
809
+ - **Intuitive Structure**: File organization matches API usage patterns
810
+ _Why it matters:_ Files with only utility functions flatten (no main export = no namespace needed), while files with main exports preserve their intended structure
811
+ - **Flexible Organization**: Mix flattened and nested patterns as needed
812
+ _Why it matters:_ You can organize files by purpose (`connection.mjs` for utilities, `config.mjs` for main objects) and slothlet automatically creates the right API structure
813
+ - **Developer Intent Respected**: Export structure signals your architectural intentions
814
+ _Why it matters:_ Default exports = "this is a main thing with methods", named exports only = "these are utility functions"
815
+ - **Backward Compatibility**: Existing APIs continue to work as expected
816
+ _Why it matters:_ The rules are additive - existing filename-matching and default export patterns still work exactly the same
817
+
697
818
  ## 🔀 How Slothlet Works: Loading Modes Explained
698
819
 
699
820
  ```mermaid
@@ -764,7 +885,7 @@ flowchart TD
764
885
  ALWAYS1 ~~~ ALWAYS2
765
886
 
766
887
  ALWAYS0@{ shape: rounded, label: "🔗 Live Bindings ALS<br/>Per-instance context isolation" }
767
- ALWAYS1@{ shape: rounded, label: "🏷️ Smart Naming & Flattening<br/>math/math.mjs api.math" }
888
+ ALWAYS1@{ shape: rounded, label: "🏷️ Smart Naming & Flattening<br/>Multiple rules for clean APIs" }
768
889
  ALWAYS2@{ shape: rounded, label: "🔄 Mixed Module Support<br/>Seamlessly mix .mjs and .cjs" }
769
890
  end
770
891