# Project Structure ## Overview The `onvif-go` project follows the **Standard Go Project Layout** optimized for a library package. This structure provides clear separation between public APIs, private implementation details, executable commands, and supporting resources. ## Directory Layout ``` onvif-go/ ├── *.go # Public API files (root level) │ ├── client.go # Main ONVIF client │ ├── device.go # Device service operations │ ├── media.go # Media service operations │ ├── ptz.go # PTZ service operations │ ├── imaging.go # Imaging service operations │ ├── types.go # Public type definitions │ ├── errors.go # Error types and handling │ └── doc.go # Package documentation │ ├── internal/ # Private packages (not importable externally) │ └── soap/ # SOAP client implementation │ ├── soap.go # SOAP envelope building and parsing │ └── soap_test.go # SOAP client tests │ ├── discovery/ # Device discovery subpackage (public) │ ├── discovery.go # WS-Discovery implementation │ └── discovery_test.go # Discovery tests │ ├── server/ # ONVIF server implementation (public) │ ├── server.go # Main server │ ├── device.go # Device service handlers │ ├── media.go # Media service handlers │ ├── ptz.go # PTZ service handlers │ ├── imaging.go # Imaging service handlers │ └── soap/ # Server SOAP handling │ └── handler.go # SOAP request handler │ ├── cmd/ # Command-line applications │ ├── onvif-cli/ # Interactive CLI tool │ ├── onvif-quick/ # Quick test utility │ ├── onvif-server/ # Virtual camera server │ ├── onvif-diagnostics/ # Diagnostic tool │ └── generate-tests/ # Test generation utility │ ├── examples/ # Example applications │ ├── device-info/ # Get device information │ ├── discovery/ # Discover cameras │ ├── ptz-control/ # PTZ operations │ ├── imaging-settings/ # Imaging configuration │ ├── complete-demo/ # Full feature demo │ ├── simplified-endpoint/ # Endpoint format demo │ ├── test-server/ # Server testing example │ └── .../ # Additional examples │ ├── docs/ # Documentation │ ├── ARCHITECTURE.md # Architecture overview │ ├── PROJECT_STRUCTURE.md # This file │ ├── SIMPLIFIED_ENDPOINT.md # Endpoint API docs │ └── .../ # Additional documentation │ ├── testdata/ # Test fixtures and data ├── testing/ # Testing helpers │ ├── .github/ # GitHub workflows and configs │ └── workflows/ │ └── release.yml # Release automation │ ├── go.mod # Go module definition ├── go.sum # Dependency checksums ├── Makefile # Build automation ├── Dockerfile # Container image ├── README.md # Project readme ├── CHANGELOG.md # Version history ├── LICENSE # License information ├── CONTRIBUTING.md # Contribution guidelines ├── QUICKSTART.md # Quick start guide └── BUILDING.md # Build instructions ``` ## Design Principles ### 1. Library-First Design As a **library package**, the main API lives at the root level: ```go import "github.com/0x524a/onvif-go" client, err := onvif.NewClient("192.168.1.100") ``` **Benefits:** - Clean, simple import path - Follows Go conventions for libraries - Easy to discover and use - No unnecessary nesting ### 2. Internal Package for Private Code The `internal/` directory contains implementation details not intended for external use: ```go // This import is ONLY available within onvif-go: import "github.com/0x524a/onvif-go/internal/soap" ``` **Go's internal package restriction:** - Cannot be imported by external projects - Enforced by the Go compiler - Allows refactoring without breaking changes **What goes in internal/**: - SOAP client implementation - Protocol-specific details - Helper functions not part of public API - Implementation details that might change ### 3. Subpackages for Additional Features Public subpackages for optional or specialized functionality: ```go // Discovery subpackage import "github.com/0x524a/onvif-go/discovery" // Server subpackage import "github.com/0x524a/onvif-go/server" ``` **When to create a subpackage:** - Logically separate feature set - Can be used independently - Different import namespace makes sense - Clear, single responsibility ### 4. Commands in cmd/ Executable applications in `cmd/` directory: ``` cmd/ ├── onvif-cli/ # Main CLI tool ├── onvif-server/ # Virtual camera └── onvif-quick/ # Quick utility ``` **Naming convention:** - Directory name = binary name - Each cmd has its own `main.go` - Can import the library: `import "github.com/0x524a/onvif-go"` **Build commands:** ```bash go build ./cmd/onvif-cli go build ./cmd/onvif-server ``` ### 5. Examples for Documentation The `examples/` directory demonstrates library usage: **Structure:** - Each example is a standalone program - Clear, focused demonstration - Can be built and run directly **Purpose:** - Supplement documentation - Show best practices - Provide starting points for users ### 6. Documentation in docs/ Comprehensive documentation in `docs/` directory: - `ARCHITECTURE.md` - Design and architecture - `PROJECT_STRUCTURE.md` - This file - `SIMPLIFIED_ENDPOINT.md` - Feature documentation - Additional guides as needed **Why separate docs/?** - Keeps root clean - Organized by topic - Easy to navigate - Scalable structure ## Import Patterns ### Public API (Root Package) ```go // Main client functionality import "github.com/0x524a/onvif-go" client, err := onvif.NewClient("192.168.1.100", onvif.WithCredentials("admin", "password"), ) ``` ### Discovery Subpackage ```go // Device discovery import "github.com/0x524a/onvif-go/discovery" devices, err := discovery.Discover(ctx, 5*time.Second) ``` ### Server Subpackage ```go // Virtual ONVIF server import "github.com/0x524a/onvif-go/server" srv := server.NewServer( server.WithCredentials("admin", "admin"), server.WithAddress(":8080"), ) ``` ### Internal Package (Library Use Only) ```go // Only usable within onvif-go itself import "github.com/0x524a/onvif-go/internal/soap" // External projects CANNOT import internal packages ``` ## File Organization Best Practices ### Root Package Files Group by service/functionality: - `client.go` - Client creation and core functionality - `device.go` - Device service methods - `media.go` - Media service methods - `ptz.go` - PTZ service methods - `imaging.go` - Imaging service methods - `types.go` - Type definitions - `errors.go` - Error types - `doc.go` - Package documentation ### Test Files Co-located with source: - `client_test.go` - Tests for client.go - `device_test.go` - Tests for device.go - Mirrors source file structure ### Large Packages For large packages, consider grouping: ``` server/ ├── server.go # Main server ├── device.go # Device handlers ├── media.go # Media handlers ├── ptz.go # PTZ handlers ├── imaging.go # Imaging handlers └── soap/ # SOAP sub-package └── handler.go ``` ## Comparison with Other Layouts ### ❌ Avoid: pkg/ Directory for Libraries ``` # DON'T DO THIS for libraries: my-lib/ └── pkg/ └── mylib/ └── mylib.go # Requires: import "github.com/user/my-lib/pkg/mylib" ``` **Why not?** - Unnecessary nesting - More complex imports - Not idiomatic for Go libraries - `pkg/` is for applications with multiple packages ### ✅ Library Layout (What We Use) ``` onvif-go/ ├── *.go # Public API at root └── internal/ # Private implementation # Clean import: import "github.com/user/onvif-go" ``` ### 📦 Application Layout (Different Use Case) For applications (not libraries): ``` my-app/ ├── cmd/ # Multiple binaries ├── internal/ # Private app code ├── pkg/ # Exported libraries from this app └── main.go # Or in cmd/ ``` ## Migration Notes ### Recent Changes **Moved SOAP to internal/:** - `soap/` → `internal/soap/` - Updated imports in: - `device.go` - `media.go` - `ptz.go` - `imaging.go` - `server/soap/handler.go` **Reason:** - SOAP client is an implementation detail - Users should interact through high-level API - Prevents tight coupling to SOAP specifics - Allows future protocol changes ### Import Updates **Old:** ```go import "github.com/0x524a/onvif-go/soap" ``` **New:** ```go import "github.com/0x524a/onvif-go/internal/soap" ``` **External users:** No changes needed (they never imported soap directly) ## Benefits of This Structure ### For Library Users 1. **Simple imports**: `import "github.com/0x524a/onvif-go"` 2. **Clear API**: Public vs private clearly separated 3. **Stable interface**: Internal changes don't affect users 4. **Good documentation**: Examples and docs organized ### For Contributors 1. **Clear organization**: Each file has single responsibility 2. **Easy navigation**: Logical directory structure 3. **Safe refactoring**: Internal package allows changes 4. **Standard layout**: Follows Go conventions ### For Maintenance 1. **Backward compatibility**: Internal changes don't break users 2. **Scalability**: Structure supports growth 3. **Testing**: Co-located tests, separate test utilities 4. **Documentation**: Organized in docs/ ## Future Considerations As the project grows: 1. **More subpackages**: Analytics, events, recording services 2. **Additional internal packages**: Caching, connection pooling 3. **Tool improvements**: Enhanced cmd/ utilities 4. **Documentation growth**: More guides in docs/ The current structure supports these additions naturally. ## References - [Standard Go Project Layout](https://github.com/golang-standards/project-layout) - [Go Blog: Package names](https://go.dev/blog/package-names) - [Effective Go](https://go.dev/doc/effective_go) - [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments) ## Summary The onvif-go project structure: - ✅ Follows Go conventions for libraries - ✅ Public API at root level - ✅ Internal package for private code - ✅ Subpackages for additional features - ✅ Clear separation of concerns - ✅ Scalable and maintainable - ✅ User-friendly imports