querykit 0.1.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.
data/lib/querykit.rb ADDED
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ # QueryKit - A lightweight query builder for Ruby
4
+ # Inspired by SqlKata, built for simplicity
5
+ #
6
+ # @author kiebor81
7
+ # @since 0.1.0
8
+
9
+ require 'date'
10
+ require 'time'
11
+
12
+ require_relative 'querykit/version'
13
+ require_relative 'querykit/configuration'
14
+ require_relative 'querykit/query'
15
+ require_relative 'querykit/insert_query'
16
+ require_relative 'querykit/update_query'
17
+ require_relative 'querykit/delete_query'
18
+ require_relative 'querykit/connection'
19
+ require_relative 'querykit/repository'
20
+ require_relative 'querykit/adapters/adapter'
21
+ require_relative 'querykit/adapters/sqlite_adapter'
22
+ require_relative 'querykit/adapters/postgresql_adapter'
23
+ require_relative 'querykit/adapters/mysql_adapter'
24
+
25
+ # QueryKit is a lightweight, fluent query builder and micro-ORM for Ruby.
26
+ # It provides a clean, chainable API for building SQL queries without the
27
+ # overhead of Active Record.
28
+ #
29
+ # @example Basic usage
30
+ # db = QueryKit.connect(:sqlite, database: 'app.db')
31
+ # users = db.get(db.query('users').where('age', '>', 18))
32
+ #
33
+ # @example Using repository pattern
34
+ # class UserRepository < QueryKit::Repository
35
+ # table 'users'
36
+ # model User
37
+ # end
38
+ # repo = UserRepository.new(db)
39
+ # user = repo.find(1)
40
+ module QueryKit
41
+ # Factory method for creating database connections
42
+ #
43
+ # @param adapter_type [Symbol] The type of database adapter to use
44
+ # (:sqlite, :postgresql, :postgres, or :mysql)
45
+ # @param config [Hash, String] Configuration for the adapter. For SQLite,
46
+ # can be a string path to the database file or a hash with :database key.
47
+ # For PostgreSQL/MySQL, should be a hash with connection parameters.
48
+ #
49
+ # @return [Connection] A new database connection instance
50
+ #
51
+ # @raise [ArgumentError] if adapter_type is not supported
52
+ #
53
+ # @example SQLite connection
54
+ # db = QueryKit.connect(:sqlite, database: 'app.db')
55
+ # # or
56
+ # db = QueryKit.connect(:sqlite, 'app.db')
57
+ #
58
+ # @example PostgreSQL connection
59
+ # db = QueryKit.connect(:postgresql,
60
+ # host: 'localhost',
61
+ # database: 'myapp',
62
+ # user: 'postgres',
63
+ # password: 'secret'
64
+ # )
65
+ #
66
+ # @example MySQL connection
67
+ # db = QueryKit.connect(:mysql,
68
+ # host: 'localhost',
69
+ # database: 'myapp',
70
+ # username: 'root',
71
+ # password: 'secret'
72
+ # )
73
+ def self.connect(adapter_type, config)
74
+ adapter = case adapter_type
75
+ when :sqlite
76
+ Adapters::SQLiteAdapter.new(config)
77
+ when :postgresql, :postgres
78
+ Adapters::PostgreSQLAdapter.new(config)
79
+ when :mysql
80
+ Adapters::MySQLAdapter.new(config)
81
+ else
82
+ raise ArgumentError, "Unknown adapter type: #{adapter_type}. " \
83
+ "Supported types: :sqlite, :postgresql, :mysql"
84
+ end
85
+
86
+ Connection.new(adapter)
87
+ end
88
+
89
+ # Load extensions into QueryKit
90
+ #
91
+ # Extensions are prepended to the Query class to allow method overrides
92
+ # and additional functionality. This enables opt-in features while keeping
93
+ # the core library minimal.
94
+ #
95
+ # @param extensions [Module, Array<Module>] One or more extension modules to load
96
+ #
97
+ # @return [void]
98
+ #
99
+ # @example Load single extension
100
+ # require 'querykit/extensions/case_when'
101
+ # QueryKit.use_extensions(QueryKit::CaseWhenExtension)
102
+ #
103
+ # @example Load multiple extensions
104
+ # QueryKit.use_extensions([QueryKit::CaseWhenExtension, MyCustomExtension])
105
+ def self.use_extensions(*extensions)
106
+ extensions.flatten.each do |extension|
107
+ Query.prepend(extension)
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,14 @@
1
+ module QueryKit
2
+ module Adapters
3
+ # Abstract adapter base class
4
+ class Adapter
5
+ def execute: (String sql, ?Array[untyped] bindings) -> Array[Hash[String, untyped]]
6
+ def begin_transaction: () -> void
7
+ def commit: () -> void
8
+ def rollback: () -> void
9
+ def close: () -> void
10
+ def last_insert_id: () -> Integer
11
+ def affected_rows: () -> Integer
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ module QueryKit
2
+ module Adapters
3
+ # MySQL database adapter
4
+ class MySQLAdapter < Adapter
5
+ def initialize: (Hash[Symbol, untyped] config) -> void
6
+ def execute: (String sql, ?Array[untyped] bindings) -> Array[Hash[String, untyped]]
7
+ def begin_transaction: () -> void
8
+ def commit: () -> void
9
+ def rollback: () -> void
10
+ def close: () -> void
11
+ def last_insert_id: () -> Integer
12
+ def affected_rows: () -> Integer
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module QueryKit
2
+ module Adapters
3
+ # PostgreSQL database adapter
4
+ class PostgreSQLAdapter < Adapter
5
+ def initialize: (Hash[Symbol, untyped] config) -> void
6
+ def execute: (String sql, ?Array[untyped] bindings) -> Array[Hash[String, untyped]]
7
+ def begin_transaction: () -> void
8
+ def commit: () -> void
9
+ def rollback: () -> void
10
+ def close: () -> void
11
+ def last_insert_id: () -> Integer
12
+ def affected_rows: () -> Integer
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module QueryKit
2
+ module Adapters
3
+ # SQLite database adapter
4
+ class SQLiteAdapter < Adapter
5
+ def initialize: (String | Hash[Symbol, untyped] config) -> void
6
+ def execute: (String sql, ?Array[untyped] bindings) -> Array[Hash[String, untyped]]
7
+ def begin_transaction: () -> void
8
+ def commit: () -> void
9
+ def rollback: () -> void
10
+ def close: () -> void
11
+ def last_insert_id: () -> Integer
12
+ def affected_rows: () -> Integer
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ module QueryKit
2
+ # Builder for SQL CASE expressions
3
+ class CaseBuilder
4
+ attr_reader column: String?
5
+ attr_reader whens: Array[Hash[Symbol, untyped]]
6
+ attr_reader else_value: untyped
7
+ attr_reader bindings: Array[untyped]
8
+
9
+ def initialize: (?String? column) -> void
10
+
11
+ # Add a WHEN condition
12
+ def when: (untyped condition, ?untyped then_value) -> self
13
+
14
+ # Set the ELSE value
15
+ def else: (untyped value) -> self
16
+
17
+ # Set an alias for the CASE expression
18
+ def as: (String alias_name) -> self
19
+
20
+ # Generate SQL
21
+ def to_sql: () -> String
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ module QueryKit
2
+ # Configuration class for global Quby settings
3
+ class Configuration
4
+ attr_accessor adapter: Symbol?
5
+ attr_accessor connection_options: Hash[Symbol, untyped]
6
+
7
+ def initialize: () -> void
8
+
9
+ # Configure with adapter and options
10
+ def setup: (Symbol adapter, Hash[Symbol, untyped] options) -> void
11
+
12
+ # Check if configuration is set
13
+ def configured?: () -> bool
14
+
15
+ # Validate configuration
16
+ def validate!: () -> void
17
+ end
18
+
19
+ # Error raised when attempting to use Quby without configuration
20
+ class ConfigurationError < StandardError
21
+ end
22
+ end
@@ -0,0 +1,36 @@
1
+ module QueryKit
2
+ # Connection class to manage database interactions
3
+ class Connection
4
+ attr_reader adapter: Adapters::Adapter
5
+
6
+ def initialize: (Adapters::Adapter adapter) -> void
7
+
8
+ # Query builder factory methods
9
+ def query: (?String? table) -> Query
10
+ def from: (String table) -> Query
11
+ def table: (String table) -> Query
12
+
13
+ # Build query objects
14
+ def insert: (?String? table) -> InsertQuery
15
+ def update: (?String? table) -> UpdateQuery
16
+ def delete: (?String? table) -> DeleteQuery
17
+
18
+ # Execute queries
19
+ def get: (Query query, ?Class? model_class) -> Array[Hash[String, untyped] | untyped]
20
+ def first: (Query query, ?Class? model_class) -> (Hash[String, untyped] | untyped)?
21
+ def execute_insert: (InsertQuery query) -> Integer
22
+ def execute_update: (UpdateQuery query) -> Integer
23
+ def execute_delete: (DeleteQuery query) -> Integer
24
+ def execute_scalar: (Query query) -> untyped
25
+
26
+ # Raw SQL
27
+ def raw: (String sql, *untyped bindings, ?model_class: Class?) -> Array[Hash[String, untyped] | untyped]
28
+
29
+ # Transaction support
30
+ def transaction: () { () -> untyped } -> untyped
31
+
32
+ private
33
+
34
+ def map_to_model: (Hash[String, untyped] row, Class model_class) -> untyped
35
+ end
36
+ end
@@ -0,0 +1,22 @@
1
+ module QueryKit
2
+ # DeleteQuery class for building DELETE SQL queries
3
+ class DeleteQuery
4
+ attr_reader table: String?
5
+ attr_reader wheres: Array[Hash[Symbol, untyped]]
6
+ attr_reader bindings: Array[untyped]
7
+
8
+ def initialize: (?String? table) -> void
9
+
10
+ # Set the table to delete from
11
+ def from: (String table) -> self
12
+
13
+ # WHERE conditions
14
+ def where: (String column, ?String? operator, ?untyped value) -> self
15
+ def where_in: (String column, Array[untyped] values) -> self
16
+ def where_null: (String column) -> self
17
+
18
+ # Generate the SQL DELETE statement
19
+ def to_sql: () -> String
20
+ def to_s: () -> String
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ module QueryKit
2
+ # Extension module that adds CASE WHEN support to Query
3
+ module CaseWhenExtension
4
+ # Start a CASE expression and return the builder
5
+ def select_case: (?String? column) -> CaseBuilder
6
+
7
+ # Override select to handle CaseBuilder objects
8
+ def select: (*String | CaseBuilder columns) -> Query
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ module QueryKit
2
+ # InsertQuery class for building INSERT SQL queries
3
+ class InsertQuery
4
+ attr_reader table: String?
5
+ attr_reader bindings: Array[untyped]
6
+
7
+ def initialize: (?String? table) -> void
8
+
9
+ # Set the table to insert into
10
+ def into: (String table) -> self
11
+
12
+ # Set the values to insert (also acts as getter via attr_reader in implementation)
13
+ def values: (Hash[String | Symbol, untyped] | Array[Hash[String | Symbol, untyped]] data) -> self
14
+
15
+ # Generate the SQL INSERT statement
16
+ def to_sql: () -> String
17
+ def to_s: () -> String
18
+ end
19
+ end
data/sig/query.rbs ADDED
@@ -0,0 +1,83 @@
1
+ module QueryKit
2
+ # Query builder for constructing SQL SELECT statements
3
+ class Query
4
+ attr_reader table: String?
5
+ attr_reader wheres: Array[Hash[Symbol, untyped]]
6
+ attr_reader selects: Array[String]
7
+ attr_reader joins: Array[Hash[Symbol, untyped]]
8
+ attr_reader orders: Array[String]
9
+ attr_reader groups: Array[String]
10
+ attr_reader limit_value: Integer?
11
+ attr_reader offset_value: Integer?
12
+ attr_accessor bindings: Array[untyped]
13
+
14
+ def initialize: (?String? table) -> void
15
+
16
+ # Table methods
17
+ def from: (String table) -> self
18
+
19
+ # SELECT methods
20
+ def select: (*String columns) -> self
21
+ def distinct: () -> self
22
+
23
+ # WHERE methods
24
+ def where: (String | Hash[String | Symbol, untyped] column, ?String? operator, ?untyped value) -> self
25
+ def or_where: (String column, ?String? operator, ?untyped value) -> self
26
+ def where_in: (String column, Array[untyped] values) -> self
27
+ def where_not_in: (String column, Array[untyped] values) -> self
28
+ def where_null: (String column) -> self
29
+ def where_not_null: (String column) -> self
30
+ def where_between: (String column, untyped min, untyped max) -> self
31
+ def where_raw: (String sql, *untyped bindings) -> self
32
+ def where_exists: (String | Query subquery) -> self
33
+ def where_not_exists: (String | Query subquery) -> self
34
+
35
+ # JOIN methods
36
+ def join: (String table, String first, ?String? operator, ?String? second) -> self
37
+ def left_join: (String table, String first, ?String? operator, ?String? second) -> self
38
+ def right_join: (String table, String first, ?String? operator, ?String? second) -> self
39
+ def cross_join: (String table) -> self
40
+
41
+ # ORDER BY, GROUP BY
42
+ def order_by: (String column, ?String direction) -> self
43
+ def group_by: (*String columns) -> self
44
+ def having: (String condition, *untyped bindings) -> self
45
+
46
+ # LIMIT, OFFSET
47
+ def limit: (Integer count) -> self
48
+ def offset: (Integer count) -> self
49
+ def skip: (Integer count) -> self
50
+ def take: (Integer count) -> self
51
+
52
+ # Pagination
53
+ def page: (Integer page_number, ?Integer per_page) -> self
54
+ def per_page: (Integer count) -> self
55
+
56
+ # Aggregates
57
+ def count: (?String? column) -> self
58
+ def sum: (String column) -> self
59
+ def avg: (String column) -> self
60
+ def min: (String column) -> self
61
+ def max: (String column) -> self
62
+
63
+ # UNION
64
+ def union: (Query query) -> self
65
+ def union_all: (Query query) -> self
66
+
67
+ # SQL generation
68
+ def to_sql: () -> String
69
+ def to_s: () -> String
70
+
71
+ private
72
+
73
+ def build_select_clause: () -> String
74
+ def build_from_clause: () -> String
75
+ def build_join_clause: () -> String
76
+ def build_where_clause: () -> String
77
+ def build_group_by_clause: () -> String
78
+ def build_having_clause: () -> String
79
+ def build_order_by_clause: () -> String
80
+ def build_limit_clause: () -> String
81
+ def build_union_clause: () -> String
82
+ end
83
+ end
data/sig/querykit.rbs ADDED
@@ -0,0 +1,25 @@
1
+ # Primary module for Quby query builder
2
+ module QueryKit
3
+ VERSION: String
4
+
5
+ # Factory method for creating database connections
6
+ def self.connect: (Symbol adapter_type, (Hash[Symbol, untyped] | String) config) -> Connection
7
+
8
+ # Load extensions into Quby
9
+ def self.use_extensions: (*Module extensions) -> void
10
+
11
+ # Get the global configuration instance
12
+ def self.configuration: () -> Configuration
13
+
14
+ # Configure Quby globally
15
+ def self.configure: () { (Configuration) -> void } -> void
16
+
17
+ # Setup with parameters
18
+ def self.setup: (Symbol adapter, Hash[Symbol, untyped] options) -> void
19
+
20
+ # Get a connection using global configuration
21
+ def self.connection: () -> Connection
22
+
23
+ # Reset configuration
24
+ def self.reset!: () -> void
25
+ end
@@ -0,0 +1,46 @@
1
+ module QueryKit
2
+ # Base repository class for implementing the repository pattern
3
+ class Repository
4
+ attr_reader db: Connection
5
+
6
+ def self.table: (String name) -> void
7
+ def self.model: (Class klass) -> void
8
+ def self.table_name: () -> String?
9
+ def self.model_class: () -> Class?
10
+
11
+ def initialize: (?Connection? db) -> void
12
+
13
+ # Query methods
14
+ def all: () -> Array[untyped]
15
+ def find: (Integer | String id) -> untyped
16
+ def find_by: (String column, untyped value) -> untyped
17
+ def where: (String column, String | untyped operator_or_value, ?untyped value) -> Array[untyped]
18
+ def where_in: (String column, Array[untyped] values) -> Array[untyped]
19
+ def where_not_in: (String column, Array[untyped] values) -> Array[untyped]
20
+ def first: () -> untyped
21
+ def count: () -> Integer
22
+ def exists?: (?Integer | String? id) -> bool
23
+
24
+ # CRUD operations
25
+ def create: (Hash[String | Symbol, untyped] attributes) -> Integer
26
+ def insert: (Hash[String | Symbol, untyped] attributes) -> Integer
27
+ def update: (Integer | String id, Hash[String | Symbol, untyped] attributes) -> Integer
28
+ def delete: (Integer | String id) -> Integer
29
+ def destroy: (Integer | String id) -> Integer
30
+
31
+ # Bulk operations
32
+ def delete_all: () -> Integer
33
+ def update_all: (Hash[String | Symbol, untyped] attributes) -> Integer
34
+
35
+ # Advanced queries
36
+ def order_by: (String column, ?String direction) -> Array[untyped]
37
+ def limit: (Integer count) -> Array[untyped]
38
+ def paginate: (Integer page, ?Integer per_page) -> Array[untyped]
39
+
40
+ private
41
+
42
+ def query: () -> Query
43
+ def table_name: () -> String
44
+ def model_class: () -> Class?
45
+ end
46
+ end
@@ -0,0 +1,25 @@
1
+ module QueryKit
2
+ # UpdateQuery class for building UPDATE SQL queries
3
+ class UpdateQuery
4
+ attr_reader sets: Hash[String, untyped]
5
+ attr_reader wheres: Array[Hash[Symbol, untyped]]
6
+ attr_reader bindings: Array[untyped]
7
+
8
+ def initialize: (?String? table) -> void
9
+
10
+ # Set the table to update (also acts as getter via attr_reader in implementation)
11
+ def table: (String table) -> self
12
+
13
+ # Set column values
14
+ def set: (Hash[String | Symbol, untyped] data) -> self
15
+
16
+ # WHERE conditions
17
+ def where: (String column, ?String? operator, ?untyped value) -> self
18
+ def where_in: (String column, Array[untyped] values) -> self
19
+ def where_null: (String column) -> self
20
+
21
+ # Generate the SQL UPDATE statement
22
+ def to_sql: () -> String
23
+ def to_s: () -> String
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: querykit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - kiebor81
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-12-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.26'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.26'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest-reporters
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ description: QueryKit is a lightweight query builder and micro-ORM inspired by SqlKata
56
+ and Dapper, providing a clean, fluent API for building SQL queries without the overhead
57
+ of Active Record. Perfect for small projects and scripts.
58
+ email:
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - CHANGELOG.md
64
+ - LICENSE
65
+ - README.md
66
+ - lib/querykit.rb
67
+ - lib/querykit/adapters/adapter.rb
68
+ - lib/querykit/adapters/mysql_adapter.rb
69
+ - lib/querykit/adapters/postgresql_adapter.rb
70
+ - lib/querykit/adapters/sqlite_adapter.rb
71
+ - lib/querykit/case_builder.rb
72
+ - lib/querykit/configuration.rb
73
+ - lib/querykit/connection.rb
74
+ - lib/querykit/delete_query.rb
75
+ - lib/querykit/extensions/case_when.rb
76
+ - lib/querykit/insert_query.rb
77
+ - lib/querykit/query.rb
78
+ - lib/querykit/repository.rb
79
+ - lib/querykit/update_query.rb
80
+ - lib/querykit/version.rb
81
+ - sig/adapters/adapter.rbs
82
+ - sig/adapters/mysql_adapter.rbs
83
+ - sig/adapters/postgresql_adapter.rbs
84
+ - sig/adapters/sqlite_adapter.rbs
85
+ - sig/case_builder.rbs
86
+ - sig/configuration.rbs
87
+ - sig/connection.rbs
88
+ - sig/delete_query.rbs
89
+ - sig/extensions/case_when.rbs
90
+ - sig/insert_query.rbs
91
+ - sig/query.rbs
92
+ - sig/querykit.rbs
93
+ - sig/repository.rbs
94
+ - sig/update_query.rbs
95
+ homepage: https://github.com/kiebor81/querykit
96
+ licenses:
97
+ - MIT
98
+ metadata:
99
+ source_code_uri: https://github.com/kiebor81/querykit
100
+ changelog_uri: https://github.com/kiebor81/querykit/blob/main/CHANGELOG.md
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 3.1.0
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubygems_version: 3.5.17
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Ruby SQL query builder and micro-ORM
120
+ test_files: []