Admin service implementation for CRUD operations on entities.
This service provides database-agnostic CRUD operations on any entity managed by the admin interface. It coordinates between schema providers, permission checks, and database operations.
Responsibilities:
Admin service implementation for CRUD operations on entities. This service provides database-agnostic CRUD operations on any entity managed by the admin interface. It coordinates between schema providers, permission checks, and database operations. Responsibilities: - Execute CRUD operations with observability - Apply pagination, filtering, sorting - Validate permissions and entity access - Transform data between DB and application formats - Handle soft/hard deletes based on schema
(build-filter-where filters)Build WHERE clause for field-specific filters.
Week 1: Simple equality filters Week 2: Advanced operators (gt, lt, contains, in, between, etc.)
Args: filters: Map of field -> value (Week 1) or field -> filter-map (Week 2) Week 1: {:role :admin :active true} Week 2: {:created-at {:op :gte :value "2024-01-01"} :status {:op :in :values [:active :pending]}}
Returns: HoneySQL WHERE clause (nil if no filters)
Example: (build-filter-where {:role :admin :active true}) ;=> [:and [:= :role :admin] [:= :active true]]
(build-filter-where {:price {:op :gte :value 100} :status {:op :in :values [:active :pending]}}) ;=> [:and [:>= :price 100] [:in :status [:active :pending]]]
Build WHERE clause for field-specific filters.
Week 1: Simple equality filters
Week 2: Advanced operators (gt, lt, contains, in, between, etc.)
Args:
filters: Map of field -> value (Week 1) or field -> filter-map (Week 2)
Week 1: {:role :admin :active true}
Week 2: {:created-at {:op :gte :value "2024-01-01"}
:status {:op :in :values [:active :pending]}}
Returns:
HoneySQL WHERE clause (nil if no filters)
Example:
(build-filter-where {:role :admin :active true})
;=> [:and [:= :role :admin] [:= :active true]]
(build-filter-where {:price {:op :gte :value 100}
:status {:op :in :values [:active :pending]}})
;=> [:and [:>= :price 100] [:in :status [:active :pending]]](build-ordering sort-field sort-dir default-field)Build ORDER BY clause.
Args: sort-field: Keyword field to sort by sort-dir: :asc or :desc default-field: Fallback field if sort-field not provided
Returns: Vector for HoneySQL :order-by clause
Example: (build-ordering :email :asc :id) ;=> [[:email :asc]]
Build ORDER BY clause. Args: sort-field: Keyword field to sort by sort-dir: :asc or :desc default-field: Fallback field if sort-field not provided Returns: Vector for HoneySQL :order-by clause Example: (build-ordering :email :asc :id) ;=> [[:email :asc]]
(build-pagination options config)Build pagination clause with safe bounds checking.
Args: options: Map with :limit, :offset, or :page and :page-size config: Admin configuration map with pagination defaults
Returns: Map with :limit and :offset
Examples: (build-pagination {:limit 20 :offset 10} config) (build-pagination {:page 2 :page-size 25} config)
Build pagination clause with safe bounds checking.
Args:
options: Map with :limit, :offset, or :page and :page-size
config: Admin configuration map with pagination defaults
Returns:
Map with :limit and :offset
Examples:
(build-pagination {:limit 20 :offset 10} config)
(build-pagination {:page 2 :page-size 25} config)(build-search-where search-term search-fields)Build WHERE clause for case-insensitive text search across multiple fields.
Args: search-term: String to search for search-fields: Vector of field keywords to search in
Returns: HoneySQL WHERE clause (nil if no search term)
Example: (build-search-where john [:email :name]) => [:or [:ilike :email percent-john-percent] [:ilike :name percent-john-percent]]
Build WHERE clause for case-insensitive text search across multiple fields.
Args:
search-term: String to search for
search-fields: Vector of field keywords to search in
Returns:
HoneySQL WHERE clause (nil if no search term)
Example:
(build-search-where john [:email :name])
=> [:or [:ilike :email percent-john-percent]
[:ilike :name percent-john-percent]](combine-where-clauses clauses)Combine multiple WHERE clauses with AND.
Args: clauses: Vector of WHERE clause expressions (nils are filtered)
Returns: Combined WHERE clause or nil
Example: (combine-where-clauses [[:= :active true] nil [:like :email "%@example.com%"]]) ;=> [:and [:= :active true] [:like :email "%@example.com%"]]
Combine multiple WHERE clauses with AND. Args: clauses: Vector of WHERE clause expressions (nils are filtered) Returns: Combined WHERE clause or nil Example: (combine-where-clauses [[:= :active true] nil [:like :email "%@example.com%"]]) ;=> [:and [:= :active true] [:like :email "%@example.com%"]]
(create-admin-service db-ctx schema-provider logger error-reporter config)Create new AdminService instance.
Args: db-ctx: Database context map with :adapter and :datasource schema-provider: ISchemaProvider implementation logger: Logger instance for operation logging error-reporter: Error reporter for exception tracking config: Admin configuration map with pagination settings
Returns: AdminService instance implementing IAdminService
Create new AdminService instance. Args: db-ctx: Database context map with :adapter and :datasource schema-provider: ISchemaProvider implementation logger: Logger instance for operation logging error-reporter: Error reporter for exception tracking config: Admin configuration map with pagination settings Returns: AdminService instance implementing IAdminService
(prepare-values-for-db m)Convert all typed values (UUID, Instant) to strings for database storage.
This ensures that at the database boundary, all complex types are converted to their string representations. This is critical for database compatibility and follows the principle that type conversions happen at system edges.
Args: m: Map with potentially typed values
Returns: Map with all UUIDs and Instants converted to strings
Example: (prepare-values-for-db {:id (UUID/randomUUID) :created-at (Instant/now) :name "John"}) ;=> {:id "123e4567-..." :created-at "2024-01-10T..." :name "John"}
Convert all typed values (UUID, Instant) to strings for database storage.
This ensures that at the database boundary, all complex types are converted
to their string representations. This is critical for database compatibility
and follows the principle that type conversions happen at system edges.
Args:
m: Map with potentially typed values
Returns:
Map with all UUIDs and Instants converted to strings
Example:
(prepare-values-for-db {:id (UUID/randomUUID)
:created-at (Instant/now)
:name "John"})
;=> {:id "123e4567-..." :created-at "2024-01-10T..." :name "John"}cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |