creem 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e7fe31044aee83bf2b64752085da9b27e4c3771e58ec40047cd83210f9fbcd45
4
+ data.tar.gz: 5f6dde7202667158a3bdfce8168afc8053d8cbf4a0885ec7cc75f21188abcbb2
5
+ SHA512:
6
+ metadata.gz: 3265a96b388350d80792a5fc2b77a70cb0961561af66b1b0d7aa0ab200c1119d163a5e5fcae3846027016e85fda0d2e0d32250f82a11a7d9b2665a4bf7134b7f
7
+ data.tar.gz: '0749ef2eeeabc5d3a762bd58acbd548cf6dfa22cf9f5d9b1983d0f2ff1f4493758a9c4b25956430b42452155830ddeb78df076b712848cddc1e222b18fdc050d'
@@ -0,0 +1,50 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+
13
+ strategy:
14
+ matrix:
15
+ ruby-version: ['3.3', '3.4']
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Ruby ${{ matrix.ruby-version }}
21
+ uses: ruby/setup-ruby@v1
22
+ with:
23
+ ruby-version: ${{ matrix.ruby-version }}
24
+ bundler-cache: true
25
+
26
+ - name: Run tests
27
+ run: bundle exec rspec
28
+
29
+ - name: Run RuboCop
30
+ run: bundle exec rubocop
31
+ continue-on-error: true
32
+
33
+ build:
34
+ runs-on: ubuntu-latest
35
+ needs: test
36
+
37
+ steps:
38
+ - uses: actions/checkout@v4
39
+
40
+ - name: Set up Ruby
41
+ uses: ruby/setup-ruby@v1
42
+ with:
43
+ ruby-version: '3.4'
44
+ bundler-cache: true
45
+
46
+ - name: Build gem
47
+ run: bundle exec rake build
48
+
49
+ - name: Verify gem can be installed
50
+ run: gem install pkg/creem-*.gem
@@ -0,0 +1,49 @@
1
+ name: Release Gem
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+ if: startsWith(github.ref, 'refs/tags/v')
12
+ permissions:
13
+ contents: write
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Ruby
19
+ uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: '3.4'
22
+ bundler-cache: true
23
+
24
+ - name: Run tests
25
+ run: bundle exec rspec
26
+
27
+ - name: Build gem
28
+ run: bundle exec rake build
29
+
30
+ - name: Publish to RubyGems
31
+ run: |
32
+ mkdir -p ~/.gem
33
+ echo ":rubygems_api_key: ${{ secrets.RUBYGEMS_API_KEY }}" > ~/.gem/credentials
34
+ chmod 0600 ~/.gem/credentials
35
+ gem push pkg/*.gem
36
+ env:
37
+ RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
38
+
39
+ - name: Create GitHub Release
40
+ uses: softprops/action-gh-release@v2
41
+ with:
42
+ files: "pkg/*.gem"
43
+ body: |
44
+ Changes in this Release
45
+ - Check CHANGELOG.md for details
46
+ draft: false
47
+ prerelease: false
48
+ env:
49
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle/
3
+ pkg/
4
+ tmp/
5
+ .rspec_status
6
+ coverage/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,126 @@
1
+ require: []
2
+
3
+ AllCops:
4
+ NewCops: enable
5
+ TargetRubyVersion: 3.1
6
+ SuggestExtensions: false
7
+ Exclude:
8
+ - "vendor/**/*"
9
+ - "tmp/**/*"
10
+ - "pkg/**/*"
11
+
12
+ # ── Style ──
13
+
14
+ Style/Documentation:
15
+ Enabled: false
16
+
17
+ Style/StringLiterals:
18
+ EnforcedStyle: double_quotes
19
+
20
+ Style/StringLiteralsInInterpolation:
21
+ EnforcedStyle: double_quotes
22
+
23
+ Style/FrozenStringLiteralComment:
24
+ Enabled: true
25
+
26
+ Style/GuardClause:
27
+ Enabled: false
28
+
29
+ Style/IfUnlessModifier:
30
+ Enabled: false
31
+
32
+ Style/Next:
33
+ Enabled: false
34
+
35
+ Style/RaiseArgs:
36
+ EnforcedStyle: compact
37
+
38
+ Style/RescueStandardError:
39
+ EnforcedStyle: implicit
40
+
41
+ Style/StringConcatenation:
42
+ Enabled: false
43
+
44
+ Style/IdenticalConditionalBranches:
45
+ Enabled: false
46
+
47
+ Style/SymbolProc:
48
+ Enabled: false
49
+
50
+ Style/ConditionalAssignment:
51
+ Enabled: false
52
+
53
+ # ── Metrics ──
54
+
55
+ Metrics/MethodLength:
56
+ Max: 30
57
+ Exclude:
58
+ - "spec/**/*"
59
+
60
+ Metrics/BlockLength:
61
+ Exclude:
62
+ - "spec/**/*"
63
+ - "*.gemspec"
64
+
65
+ Metrics/AbcSize:
66
+ Max: 35
67
+ Exclude:
68
+ - "spec/**/*"
69
+
70
+ Metrics/CyclomaticComplexity:
71
+ Max: 12
72
+
73
+ Metrics/PerceivedComplexity:
74
+ Max: 12
75
+
76
+ Metrics/ClassLength:
77
+ Max: 250
78
+
79
+ Metrics/ParameterLists:
80
+ Max: 8
81
+
82
+ # ── Layout ──
83
+
84
+ Layout/LineLength:
85
+ Max: 120
86
+ Exclude:
87
+ - "spec/**/*"
88
+
89
+ Layout/FirstArrayElementIndentation:
90
+ EnforcedStyle: consistent
91
+
92
+ Layout/FirstHashElementIndentation:
93
+ EnforcedStyle: consistent
94
+
95
+ # ── Naming ──
96
+
97
+ Naming/AccessorMethodName:
98
+ Enabled: false
99
+
100
+ Naming/MethodParameterName:
101
+ Enabled: false
102
+
103
+ Naming/PredicateMethod:
104
+ Enabled: false
105
+
106
+ # ── Lint ──
107
+
108
+ Lint/UnusedBlockArgument:
109
+ Enabled: false
110
+
111
+ Lint/UnusedMethodArgument:
112
+ Enabled: false
113
+
114
+ Lint/UnderscorePrefixedVariableName:
115
+ Enabled: false
116
+
117
+ Lint/SharedMutableDefault:
118
+ Enabled: false
119
+
120
+ # ── Gemspec ──
121
+
122
+ Gemspec/RequireMFA:
123
+ Enabled: false
124
+
125
+ Gemspec/DevelopmentDependencies:
126
+ Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.3
data/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ ## [0.1.0] - 2024-01-01
4
+
5
+ ### Added
6
+
7
+ - Initial release
8
+ - Products API (list, retrieve)
9
+ - Checkouts API (create)
10
+ - Subscriptions API (list, retrieve, update, cancel)
11
+ - Customers API (list, retrieve, billing portal)
12
+ - Transactions API (list)
13
+ - Licenses API (list, validate, activate, deactivate)
14
+ - Discounts API (list)
15
+ - Webhook signature verification
16
+ - Test mode support
17
+ - Configurable timeouts
data/CLAUDE.md ADDED
@@ -0,0 +1,38 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Common Commands
6
+
7
+ Ruby is pinned to 3.3 via `.ruby-version` and commands are run through `mise exec -- bundle exec ...`. Use the Makefile rather than invoking `bundle`/`rspec`/`rubocop` directly so the right toolchain is used.
8
+
9
+ - `make install` — install dependencies
10
+ - `make test` — run the full RSpec suite
11
+ - `make test TEST=spec/resources/checkouts_spec.rb` — run a single spec file (any path works; `TEST=.` is the default and means "everything")
12
+ - `make lint` / `make format` — RuboCop check / autocorrect
13
+ - `make console` — `irb -r creem`
14
+ - `make build` — build the gem via `rake build`
15
+ - `make tag` / `make tag VERSION=x.y.z` — bumps `lib/creem/version.rb`, commits "Release vX", tags, and pushes both branch and tag. Auto-increments the patch when `VERSION` is omitted; the `lib/creem/version.rb` write is done by `sed`, so the file's `VERSION = '...'` line format must stay matchable.
16
+
17
+ A single test can also be run with `mise exec -- bundle exec rspec spec/path_spec.rb:LINE` if you need line-level focus.
18
+
19
+ ## Architecture
20
+
21
+ This gem is a thin HTTP client over the Creem REST API. Three layers:
22
+
23
+ 1. **`Creem` module + `Configuration`** ([lib/creem.rb](lib/creem.rb), [lib/creem/configuration.rb](lib/creem/configuration.rb)) — holds the global `Creem.configuration` (api_key, test_mode, timeouts). `base_url` is derived from `test_mode` and switches between `PRODUCTION_BASE_URL` and `TEST_BASE_URL` constants defined on the module.
24
+ 2. **`Creem::Client`** ([lib/creem/client.rb](lib/creem/client.rb)) — owns its own `Configuration` copy (seeded from globals at init), exposes one memoized accessor per resource, and is the only place that talks `Net::HTTP`. Auth is sent as the `x-api-key` header. All requests go through `request → build_uri → build_http → build_request → handle_response`; `handle_response` is what maps HTTP status codes to the error hierarchy.
25
+ 3. **`Creem::Resources::*`** ([lib/creem/resources/](lib/creem/resources/)) — each resource subclasses `Resources::Base`, which only holds a reference to the client and forwards `get`/`post`. Resources are pure mappers from keyword args to request bodies/query params; they do not parse responses, they return the raw `Hash` from `JSON.parse`. When adding a new resource: subclass `Base`, register a memoized accessor on `Client`, and `require_relative` it from `lib/creem.rb`.
26
+
27
+ **Endpoint quirks worth knowing before editing:**
28
+ - Listing uses different paths per resource: `/subscriptions/search`, `/licenses/search`, `/customers/list`, but `/transactions/...`. Don't normalize these — they reflect the upstream API.
29
+ - `retrieve` typically passes the id as a **query parameter** (e.g. `GET /subscriptions?subscription_id=...`), not as a path segment. `Subscriptions#update` and `#cancel` are the exceptions that use path segments.
30
+ - `Subscriptions#cancel` sends camelCase `onExecute` while everything else is snake_case — intentional, matches the API.
31
+
32
+ **Errors** ([lib/creem/errors.rb](lib/creem/errors.rb)) — `ApiError` (base) carries `status` and `body`. Subclasses are mapped by status code in `Client#handle_response`: 400→`BadRequestError`, 401→`AuthenticationError`, 404→`NotFoundError`, 429→`RateLimitError`, 5xx→`ServerError`. `ConfigurationError` and `WebhookSignatureError` are separate (`< Error`, not `< ApiError`).
33
+
34
+ **Webhooks** ([lib/creem/webhook.rb](lib/creem/webhook.rb)) — HMAC-SHA256 over the raw payload, compared with `OpenSSL.fixed_length_secure_compare`. Use `Webhook.construct_event` (verifies + parses) as the public entry point.
35
+
36
+ ## Testing Conventions
37
+
38
+ [spec/spec_helper.rb](spec/spec_helper.rb) resets `Creem.configuration` before every example and disables real network access via WebMock. Two helpers — `stub_creem_get` and `stub_creem_post` — should be used for all HTTP stubs; they assert the `x-api-key` header and JSON-encode the request body. `build_client` produces a client with a fixed test api_key. New resource specs should follow this pattern rather than rolling their own WebMock stubs.
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
6
+
7
+ group :development, :test do
8
+ gem "rake", "~> 13.0"
9
+ gem "rspec", "~> 3.12"
10
+ gem "rubocop", "~> 1.50"
11
+ gem "webmock", "~> 3.18"
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,85 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ creem (0.0.1)
5
+ net-http
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ addressable (2.9.0)
11
+ public_suffix (>= 2.0.2, < 8.0)
12
+ ast (2.4.3)
13
+ bigdecimal (4.1.2)
14
+ crack (1.0.1)
15
+ bigdecimal
16
+ rexml
17
+ diff-lcs (1.6.2)
18
+ hashdiff (1.2.1)
19
+ json (2.19.5)
20
+ language_server-protocol (3.17.0.5)
21
+ lint_roller (1.1.0)
22
+ net-http (0.9.1)
23
+ uri (>= 0.11.1)
24
+ parallel (2.1.0)
25
+ parser (3.3.11.1)
26
+ ast (~> 2.4.1)
27
+ racc
28
+ prism (1.9.0)
29
+ public_suffix (7.0.5)
30
+ racc (1.8.1)
31
+ rainbow (3.1.1)
32
+ rake (13.4.2)
33
+ regexp_parser (2.12.0)
34
+ rexml (3.4.4)
35
+ rspec (3.13.2)
36
+ rspec-core (~> 3.13.0)
37
+ rspec-expectations (~> 3.13.0)
38
+ rspec-mocks (~> 3.13.0)
39
+ rspec-core (3.13.6)
40
+ rspec-support (~> 3.13.0)
41
+ rspec-expectations (3.13.5)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.13.0)
44
+ rspec-mocks (3.13.8)
45
+ diff-lcs (>= 1.2.0, < 2.0)
46
+ rspec-support (~> 3.13.0)
47
+ rspec-support (3.13.7)
48
+ rubocop (1.86.2)
49
+ json (~> 2.3)
50
+ language_server-protocol (~> 3.17.0.2)
51
+ lint_roller (~> 1.1.0)
52
+ parallel (>= 1.10)
53
+ parser (>= 3.3.0.2)
54
+ rainbow (>= 2.2.2, < 4.0)
55
+ regexp_parser (>= 2.9.3, < 3.0)
56
+ rubocop-ast (>= 1.49.0, < 2.0)
57
+ ruby-progressbar (~> 1.7)
58
+ unicode-display_width (>= 2.4.0, < 4.0)
59
+ rubocop-ast (1.49.1)
60
+ parser (>= 3.3.7.2)
61
+ prism (~> 1.7)
62
+ ruby-progressbar (1.13.0)
63
+ unicode-display_width (3.2.0)
64
+ unicode-emoji (~> 4.1)
65
+ unicode-emoji (4.2.0)
66
+ uri (1.1.1)
67
+ webmock (3.26.2)
68
+ addressable (>= 2.8.0)
69
+ crack (>= 0.3.2)
70
+ hashdiff (>= 0.4.0, < 2.0.0)
71
+
72
+ PLATFORMS
73
+ arm64-darwin
74
+ ruby
75
+ x86_64-linux
76
+
77
+ DEPENDENCIES
78
+ creem!
79
+ rake (~> 13.0)
80
+ rspec (~> 3.12)
81
+ rubocop (~> 1.50)
82
+ webmock (~> 3.18)
83
+
84
+ BUNDLED WITH
85
+ 2.6.8
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Creem Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/Makefile ADDED
@@ -0,0 +1,108 @@
1
+ .PHONY: all install format lint test test_watch clean build console tag help
2
+
3
+ all: help
4
+
5
+ ######################
6
+ # SETUP
7
+ ######################
8
+
9
+ install: ## Install dependencies
10
+ mise exec -- bundle install
11
+
12
+ ######################
13
+ # TESTING AND COVERAGE
14
+ ######################
15
+
16
+ TEST ?= .
17
+
18
+ test: ## Run the test suite (TEST=path/to/spec.rb to run a specific file)
19
+ mise exec -- bundle exec rspec $(if $(filter-out .,$(TEST)),$(TEST),)
20
+
21
+ ######################
22
+ # LINTING AND FORMATTING
23
+ ######################
24
+
25
+ format: ## Run code formatters
26
+ mise exec -- bundle exec rubocop -a
27
+
28
+ lint: ## Run linters
29
+ mise exec -- bundle exec rubocop
30
+
31
+ ######################
32
+ # BUILD AND RELEASE
33
+ ######################
34
+
35
+ build: ## Build the gem
36
+ mise exec -- bundle exec rake build
37
+
38
+ clean: ## Remove build artifacts
39
+ rm -f *.gem
40
+ rm -f creem-*.gem
41
+ rm -rf pkg/ tmp/ coverage/ .rspec_status
42
+
43
+ console: ## Start an interactive console with the gem loaded
44
+ mise exec -- bundle exec irb -r creem
45
+
46
+ tag: ## Create and push a version tag. Usage: make tag [VERSION=x.y.z]
47
+ @git fetch --tags; \
48
+ if [ -z "$(VERSION)" ]; then \
49
+ LATEST=$$(git tag -l 'v[0-9]*' --sort=-v:refname | head -n1); \
50
+ if [ -z "$$LATEST" ]; then \
51
+ NEW_TAG="v0.0.1"; \
52
+ else \
53
+ MAJOR=$$(echo $$LATEST | sed 's/^v//' | cut -d. -f1); \
54
+ MINOR=$$(echo $$LATEST | sed 's/^v//' | cut -d. -f2); \
55
+ PATCH=$$(echo $$LATEST | sed 's/^v//' | cut -d. -f3); \
56
+ PATCH=$$((PATCH + 1)); \
57
+ NEW_TAG="v$$MAJOR.$$MINOR.$$PATCH"; \
58
+ fi; \
59
+ else \
60
+ NEW_TAG="v$(VERSION)"; \
61
+ LATEST=$$(git tag -l 'v[0-9]*' --sort=-v:refname | head -n1); \
62
+ if [ "$$LATEST" = "$$NEW_TAG" ]; then \
63
+ echo "Tag $$NEW_TAG already exists on remote, deleting and re-pushing..."; \
64
+ git tag -d "$$NEW_TAG" 2>/dev/null || true; \
65
+ git push origin --delete "$$NEW_TAG" 2>/dev/null || true; \
66
+ elif git tag -l "$$NEW_TAG" | grep -q "$$NEW_TAG"; then \
67
+ echo "Error: Tag $$NEW_TAG exists but is not the latest tag (latest: $$LATEST). Aborting."; \
68
+ exit 1; \
69
+ fi; \
70
+ fi; \
71
+ NEW_VERSION=$$(echo $$NEW_TAG | sed 's/^v//'); \
72
+ echo "Updating version to $$NEW_VERSION ..."; \
73
+ sed -i '' "s/VERSION = [\"'].*[\"']/VERSION = '$$NEW_VERSION'/" lib/creem/version.rb; \
74
+ mise exec -- bundle install; \
75
+ git add lib/creem/version.rb Gemfile.lock; \
76
+ git commit -m "Release $$NEW_TAG" --allow-empty; \
77
+ git tag "$$NEW_TAG"; \
78
+ echo "Pushing tag $$NEW_TAG ..."; \
79
+ git push origin HEAD; \
80
+ git push origin "$$NEW_TAG"; \
81
+ echo "Done! Tagged and pushed $$NEW_TAG"
82
+
83
+ ######################
84
+ # HELP
85
+ ######################
86
+
87
+ help: ## Show this help
88
+ @echo '=========================='
89
+ @echo ' Creem SDK — Makefile'
90
+ @echo '=========================='
91
+ @echo ''
92
+ @echo 'SETUP'
93
+ @echo ' make install — install dependencies'
94
+ @echo ''
95
+ @echo 'TESTING'
96
+ @echo ' make test — run the full test suite'
97
+ @echo ' make test TEST=spec/... — run a specific test file'
98
+ @echo ''
99
+ @echo 'LINTING & FORMATTING'
100
+ @echo ' make format — run code formatters'
101
+ @echo ' make lint — run linters'
102
+ @echo ''
103
+ @echo 'BUILD & RELEASE'
104
+ @echo ' make build — build the gem'
105
+ @echo ' make clean — remove build artifacts'
106
+ @echo ' make console — start interactive console'
107
+ @echo ' make tag — auto-increment patch version, tag & push'
108
+ @echo ' make tag VERSION=x.y.z — tag a specific version & push'