cloudflare-d1 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/README.md ADDED
@@ -0,0 +1,253 @@
1
+ # Cloudflare D1 Gem
2
+
3
+ [![CI](https://github.com/your-username/cloudflare-d1/actions/workflows/ci.yml/badge.svg)](https://github.com/your-username/cloudflare-d1/actions/workflows/ci.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/cloudflare-d1.svg)](https://badge.fury.io/rb/cloudflare-d1)
5
+
6
+ Ruby adapters for [Cloudflare D1](https://developers.cloudflare.com/d1/) - SQLite at the edge.
7
+
8
+ Provides both **ActiveRecord** and **Sequel** adapters to use D1 databases from Ruby applications.
9
+
10
+ ## Features
11
+
12
+ - **ActiveRecord adapter** - Full Rails integration with migrations
13
+ - **Sequel adapter** - Lightweight ORM for non-Rails apps
14
+ - **Database management** - Rake tasks for creating/dropping databases
15
+ - **Local development** - Use local SQLite for dev, D1 for production
16
+ - **Cloudflare Containers** - Example Roda app deployable to Cloudflare
17
+
18
+ ## Installation
19
+
20
+ Add to your `Gemfile`:
21
+
22
+ ```ruby
23
+ gem "cloudflare-d1"
24
+ ```
25
+
26
+ Then run:
27
+
28
+ ```bash
29
+ bundle install
30
+ ```
31
+
32
+ Or install directly:
33
+
34
+ ```bash
35
+ gem install cloudflare-d1
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ ### ActiveRecord (Rails)
41
+
42
+ Configure in `config/database.yml`:
43
+
44
+ ```yaml
45
+ production:
46
+ adapter: cloudflare_d1
47
+ account_id: <%= ENV['CLOUDFLARE_ACCOUNT_ID'] %>
48
+ api_token: <%= ENV['CLOUDFLARE_API_TOKEN'] %>
49
+ database_id: <%= ENV['DATABASE_ID'] %>
50
+ ```
51
+
52
+ Use standard ActiveRecord:
53
+
54
+ ```ruby
55
+ class User < ActiveRecord::Base
56
+ end
57
+
58
+ # CRUD operations
59
+ user = User.create(name: "Alice", email: "alice@example.com")
60
+ User.where(email: "alice@example.com").first
61
+ user.update(name: "Alice Smith")
62
+ user.destroy
63
+ ```
64
+
65
+ Run migrations:
66
+
67
+ ```bash
68
+ rake db:create # Create D1 database
69
+ rake db:migrate # Run migrations
70
+ rake db:rollback # Rollback migrations
71
+ ```
72
+
73
+ ### Sequel (Non-Rails)
74
+
75
+ Connect to D1:
76
+
77
+ ```ruby
78
+ require "sequel"
79
+ require "sequel/adapters/cloudflare_d1"
80
+
81
+ DB = Sequel.connect(
82
+ adapter: :cloudflare_d1,
83
+ account_id: ENV["CLOUDFLARE_ACCOUNT_ID"],
84
+ api_token: ENV["CLOUDFLARE_API_TOKEN"],
85
+ database: ENV["DATABASE_ID"]
86
+ )
87
+
88
+ # Use Sequel
89
+ DB[:users].insert(name: "Bob", email: "bob@example.com")
90
+ DB[:users].where(email: "bob@example.com").all
91
+ DB[:users].where(id: 1).update(name: "Robert")
92
+ DB[:users].where(id: 1).delete
93
+ ```
94
+
95
+ Run migrations:
96
+
97
+ ```bash
98
+ rake sequel:db:migrate
99
+ ```
100
+
101
+ ## Local Development
102
+
103
+ For local development, use SQLite directly instead of making API calls:
104
+
105
+ ```ruby
106
+ # config/database.yml
107
+ development:
108
+ adapter: sqlite3
109
+ database: db/development.sqlite3
110
+
111
+ production:
112
+ adapter: cloudflare_d1
113
+ account_id: <%= ENV['CLOUDFLARE_ACCOUNT_ID'] %>
114
+ api_token: <%= ENV['CLOUDFLARE_API_TOKEN'] %>
115
+ database_id: <%= ENV['DATABASE_ID'] %>
116
+ ```
117
+
118
+ Or for Sequel:
119
+
120
+ ```ruby
121
+ if ENV["RACK_ENV"] == "production"
122
+ DB = Sequel.connect(adapter: :cloudflare_d1, ...)
123
+ else
124
+ DB = Sequel.connect("sqlite://db/development.db")
125
+ end
126
+ ```
127
+
128
+ ## Examples
129
+
130
+ ### Roda + Cloudflare Containers
131
+
132
+ See the complete example in [`examples/roda/`](examples/roda/):
133
+
134
+ ```bash
135
+ cd examples/roda
136
+ ./setup.sh # Automated setup and deployment
137
+ ```
138
+
139
+ Features:
140
+ - Full CRUD API
141
+ - Automatic migrations
142
+ - Deployable to Cloudflare Containers
143
+ - Local development with SQLite
144
+
145
+ ## Configuration
146
+
147
+ ### Environment Variables
148
+
149
+ Set these environment variables:
150
+
151
+ ```bash
152
+ export CLOUDFLARE_ACCOUNT_ID=your_account_id
153
+ export CLOUDFLARE_API_TOKEN=your_api_token
154
+ export DATABASE_ID=your_database_uuid
155
+ ```
156
+
157
+ Get your credentials:
158
+ - **Account ID**: `wrangler whoami` or Cloudflare dashboard
159
+ - **API Token**: Dashboard → My Profile → API Tokens
160
+ - Create token with "Edit Cloudflare Workers" template
161
+ - Include D1 Database permissions
162
+ - **Database ID**: `wrangler d1 create my-database`
163
+
164
+ ### Creating a D1 Database
165
+
166
+ Using Wrangler:
167
+
168
+ ```bash
169
+ wrangler d1 create my-database
170
+ ```
171
+
172
+ Or using the gem:
173
+
174
+ ```bash
175
+ # ActiveRecord
176
+ rake db:create
177
+
178
+ # Sequel
179
+ DATABASE_NAME=my-database rake sequel:db:create
180
+ ```
181
+
182
+ ## Rake Tasks
183
+
184
+ ### ActiveRecord
185
+
186
+ ```bash
187
+ rake db:create # Create D1 database
188
+ rake db:drop # Drop D1 database
189
+ rake db:list # List all D1 databases
190
+ rake db:migrate # Run migrations
191
+ rake db:rollback # Rollback migrations
192
+ rake db:migrate_status # Show migration status
193
+ rake db:reset # Drop, create, migrate
194
+ rake db:setup # Create and migrate
195
+ ```
196
+
197
+ ### Sequel
198
+
199
+ ```bash
200
+ rake sequel:db:create # Create D1 database
201
+ rake sequel:db:drop # Drop D1 database
202
+ rake sequel:db:list # List all D1 databases
203
+ rake sequel:db:migrate # Run migrations
204
+ rake sequel:db:rollback # Rollback migrations
205
+ rake sequel:db:status # Show migration status
206
+ rake sequel:db:reset # Drop, create, migrate
207
+ rake sequel:db:setup # Create and migrate
208
+ ```
209
+
210
+ ## Limitations
211
+
212
+ Due to D1's architecture:
213
+
214
+ - **No DDL transactions** - Schema changes aren't wrapped in transactions
215
+ - **No savepoints** - Transaction savepoints not supported
216
+ - **No connection pooling** - Each query is an HTTP request
217
+ - **API-only access** - D1 is not directly accessible outside Cloudflare
218
+
219
+ These are D1 limitations, not gem limitations.
220
+
221
+ ## Development
222
+
223
+ After checking out the repo:
224
+
225
+ ```bash
226
+ bundle install
227
+ rake test
228
+ ```
229
+
230
+ To install this gem onto your local machine:
231
+
232
+ ```bash
233
+ bundle exec rake install
234
+ ```
235
+
236
+ ## Contributing
237
+
238
+ Bug reports and pull requests are welcome on GitHub.
239
+
240
+ ## Releasing
241
+
242
+ See [RELEASING.md](RELEASING.md) for release instructions.
243
+
244
+ ## License
245
+
246
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
247
+
248
+ ## Links
249
+
250
+ - [Cloudflare D1 Documentation](https://developers.cloudflare.com/d1/)
251
+ - [Cloudflare Containers](https://developers.cloudflare.com/containers/)
252
+ - [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/)
253
+ - [RubyGems](https://rubygems.org/gems/cloudflare-d1)
data/RELEASING.md ADDED
@@ -0,0 +1,199 @@
1
+ # Releasing cloudflare-d1 Gem
2
+
3
+ This document describes the process for releasing new versions of the `cloudflare-d1` gem.
4
+
5
+ ## Prerequisites
6
+
7
+ ### 1. RubyGems API Key
8
+
9
+ Set up your RubyGems API key as a GitHub secret:
10
+
11
+ 1. Get your API key from [RubyGems.org](https://rubygems.org/profile/edit)
12
+ - Sign in to RubyGems
13
+ - Go to "Edit Profile"
14
+ - Under "API Access", create a new API key with push permissions
15
+
16
+ 2. Add to GitHub repository secrets:
17
+ - Go to repository Settings → Secrets and variables → Actions
18
+ - Click "New repository secret"
19
+ - Name: `RUBYGEMS_API_KEY`
20
+ - Value: Your RubyGems API key
21
+
22
+ ### 2. Repository Permissions
23
+
24
+ Make sure you have:
25
+ - Write access to the repository
26
+ - Permission to push tags
27
+ - Permission to create releases
28
+
29
+ ## Release Process
30
+
31
+ ### 1. Update Version
32
+
33
+ Edit `lib/cloudflare/d1/version.rb`:
34
+
35
+ ```ruby
36
+ module Cloudflare
37
+ module D1
38
+ VERSION = "0.2.0" # Update this
39
+ end
40
+ end
41
+ ```
42
+
43
+ ### 2. Update Changelog
44
+
45
+ Edit `CHANGELOG.md`:
46
+
47
+ ```markdown
48
+ ## [0.2.0] - 2024-01-15
49
+
50
+ ### Added
51
+ - New feature description
52
+
53
+ ### Changed
54
+ - Changed feature description
55
+
56
+ ### Fixed
57
+ - Bug fix description
58
+ ```
59
+
60
+ ### 3. Commit Changes
61
+
62
+ ```bash
63
+ git add lib/cloudflare/d1/version.rb CHANGELOG.md
64
+ git commit -m "Bump version to 0.2.0"
65
+ git push origin master
66
+ ```
67
+
68
+ ### 4. Create and Push Tag
69
+
70
+ ```bash
71
+ # Create annotated tag
72
+ git tag -a v0.2.0 -m "Release version 0.2.0"
73
+
74
+ # Push tag to trigger release workflow
75
+ git push origin v0.2.0
76
+ ```
77
+
78
+ ### 5. Watch Release Build
79
+
80
+ The GitHub Actions workflow will automatically:
81
+ 1. Run all tests
82
+ 2. Build the gem
83
+ 3. Publish to RubyGems.org
84
+ 4. Create GitHub release with gem artifact
85
+ 5. Generate release notes
86
+
87
+ Monitor the workflow at:
88
+ https://github.com/your-username/cloudflare-d1/actions
89
+
90
+ ### 6. Verify Release
91
+
92
+ Check that the gem is available:
93
+
94
+ ```bash
95
+ gem list cloudflare-d1 --remote --all
96
+ ```
97
+
98
+ Or visit: https://rubygems.org/gems/cloudflare-d1
99
+
100
+ ## Manual Release (If Needed)
101
+
102
+ If automated release fails:
103
+
104
+ ```bash
105
+ # Build gem
106
+ gem build cloudflare-d1.gemspec
107
+
108
+ # Test locally (optional)
109
+ gem install ./cloudflare-d1-0.2.0.gem
110
+
111
+ # Push to RubyGems
112
+ gem push cloudflare-d1-0.2.0.gem
113
+ ```
114
+
115
+ ## Versioning
116
+
117
+ Follow [Semantic Versioning](https://semver.org/):
118
+
119
+ - **MAJOR** version (1.0.0): Breaking changes
120
+ - **MINOR** version (0.2.0): New features, backward compatible
121
+ - **PATCH** version (0.1.1): Bug fixes, backward compatible
122
+
123
+ Examples:
124
+ - `0.1.0` → `0.2.0`: Added Sequel adapter (new feature)
125
+ - `0.2.0` → `0.2.1`: Fixed connection bug (bug fix)
126
+ - `0.2.1` → `1.0.0`: Changed API (breaking change)
127
+
128
+ ## Troubleshooting
129
+
130
+ ### Release workflow failed
131
+
132
+ Check the Actions logs:
133
+ ```bash
134
+ # View recent workflow runs
135
+ gh run list --workflow=release.yml
136
+
137
+ # View logs for specific run
138
+ gh run view <run-id> --log
139
+ ```
140
+
141
+ Common issues:
142
+ - **Tests failed**: Fix tests and create new tag
143
+ - **RubyGems authentication failed**: Check `RUBYGEMS_API_KEY` secret
144
+ - **Gem already exists**: Version already published, bump version
145
+
146
+ ### Yank a release (if needed)
147
+
148
+ If you need to remove a problematic release:
149
+
150
+ ```bash
151
+ gem yank cloudflare-d1 -v 0.2.0
152
+ ```
153
+
154
+ **Note:** Only yank for serious issues (security, broken functionality). Prefer releasing a patch version instead.
155
+
156
+ ## Release Checklist
157
+
158
+ Before releasing:
159
+
160
+ - [ ] All tests pass locally
161
+ - [ ] RuboCop violations fixed
162
+ - [ ] Version bumped in `version.rb`
163
+ - [ ] CHANGELOG updated
164
+ - [ ] README updated (if needed)
165
+ - [ ] Examples tested
166
+ - [ ] Breaking changes documented
167
+
168
+ After releasing:
169
+
170
+ - [ ] Gem appears on RubyGems.org
171
+ - [ ] GitHub release created
172
+ - [ ] Release notes look good
173
+ - [ ] Announcement (optional):
174
+ - Twitter/X
175
+ - Ruby Weekly
176
+ - Blog post
177
+
178
+ ## Pre-release Versions
179
+
180
+ For beta/RC releases:
181
+
182
+ ```ruby
183
+ # lib/cloudflare/d1/version.rb
184
+ VERSION = "0.2.0.beta.1"
185
+ ```
186
+
187
+ ```bash
188
+ git tag -a v0.2.0.beta.1 -m "Release version 0.2.0.beta.1"
189
+ git push origin v0.2.0.beta.1
190
+ ```
191
+
192
+ Install pre-release:
193
+ ```bash
194
+ gem install cloudflare-d1 --pre
195
+ ```
196
+
197
+ ## Questions?
198
+
199
+ Open an issue or discussion on GitHub.
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ end
11
+
12
+ require "rubocop/rake_task"
13
+
14
+ RuboCop::RakeTask.new
15
+
16
+ task default: %i[test rubocop]
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/cloudflare/d1/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "cloudflare-d1"
7
+ spec.version = Cloudflare::D1::VERSION
8
+ spec.authors = ["Ben"]
9
+ spec.email = ["ben@dee.mx"]
10
+
11
+ spec.summary = "ActiveRecord and Sequel adapters for Cloudflare D1 databases"
12
+ spec.description = "Custom ActiveRecord and Sequel adapters that allow Ruby applications to use Cloudflare D1 databases via the REST API"
13
+ spec.homepage = "https://github.com/ben/cloudflare-d1"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.6.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/ben/cloudflare-d1"
19
+ spec.metadata["changelog_uri"] = "https://github.com/ben/cloudflare-d1/blob/master/CHANGELOG.md"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(__dir__) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (File.expand_path(f) == __FILE__) ||
26
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
27
+ end
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ # Development dependencies
34
+ spec.add_development_dependency "minitest", "~> 5.0"
35
+ spec.add_development_dependency "rubocop", "~> 1.0"
36
+ spec.add_development_dependency "rake", "~> 13.0"
37
+ spec.add_development_dependency "webmock", "~> 3.0"
38
+ spec.add_development_dependency "activerecord", ">= 6.0"
39
+ spec.add_development_dependency "sequel", ">= 5.0"
40
+ end
@@ -0,0 +1,14 @@
1
+ .git
2
+ .gitignore
3
+ README.md
4
+ .env
5
+ .env.*
6
+ *.log
7
+ tmp/
8
+ log/
9
+ coverage/
10
+ .bundle/
11
+ vendor/bundle
12
+ .rspec
13
+ spec/
14
+ test/
@@ -0,0 +1,11 @@
1
+ .env
2
+ .env.*
3
+ *.log
4
+ tmp/
5
+ log/
6
+ .bundle/
7
+ vendor/bundle
8
+ .wrangler/
9
+ db/*.db
10
+ db/*.db-shm
11
+ db/*.db-wal
@@ -0,0 +1,21 @@
1
+ FROM ruby:3.2-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Install system dependencies
6
+ RUN apt-get update && apt-get install -y \
7
+ build-essential \
8
+ && rm -rf /var/lib/apt/lists/*
9
+
10
+ # Copy Gemfile and install dependencies
11
+ COPY Gemfile Gemfile.lock ./
12
+ RUN bundle install --without development test
13
+
14
+ # Copy application code
15
+ COPY . .
16
+
17
+ # Expose port
18
+ EXPOSE 8080
19
+
20
+ # Run the application
21
+ CMD ["ruby", "app.rb"]
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "roda", "~> 3.0"
4
+ gem "puma", "~> 6.0"
5
+ gem "sequel", "~> 5.0"
6
+ gem "cloudflare-d1", path: "../.."
7
+ gem "rack", "~> 3.0"
8
+
9
+ group :development, :test do
10
+ gem "sqlite3", "~> 1.6" # Local SQLite for development
11
+ gem "rackup"
12
+ end
@@ -0,0 +1,35 @@
1
+ PATH
2
+ remote: ../..
3
+ specs:
4
+ cloudflare-d1 (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ bigdecimal (3.3.1)
10
+ nio4r (2.7.5)
11
+ puma (6.6.1)
12
+ nio4r (~> 2.0)
13
+ rack (3.2.4)
14
+ rackup (2.2.1)
15
+ rack (>= 3)
16
+ rake (13.3.1)
17
+ roda (3.97.0)
18
+ rack
19
+ sequel (5.98.0)
20
+ bigdecimal
21
+
22
+ PLATFORMS
23
+ arm64-darwin-24
24
+
25
+ DEPENDENCIES
26
+ cloudflare-d1!
27
+ puma (~> 6.0)
28
+ rack (~> 3.0)
29
+ rackup
30
+ rake
31
+ roda (~> 3.0)
32
+ sequel (~> 5.0)
33
+
34
+ BUNDLED WITH
35
+ 2.4.19