Skip to content

Commit 7470aa3

Browse files
jnunemakerclaude
andcommitted
Use Typecast for JSON serialization in Cloud migrate/push
Replace direct JSON.generate/JSON.parse calls with Typecast.to_json and Typecast.from_json for consistency with the rest of the codebase. Add CLAUDE.md guidance on using Typecast and Http::Client. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d19e3f9 commit 7470aa3

2 files changed

Lines changed: 15 additions & 8 deletions

File tree

CLAUDE.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ The project is structured as multiple gems:
6969
**Memoization**: Automatic caching of feature checks within request/thread scope
7070
**Type Safety**: Strong typing system for actors, percentages, and other values
7171

72+
### Serialization and HTTP
73+
74+
Use `Flipper::Typecast` for JSON and gzip serialization instead of calling `JSON.generate`/`JSON.parse` or `Zlib` directly:
75+
- `Typecast.to_json(hash)` / `Typecast.from_json(string)` for JSON serialization
76+
- `Typecast.to_gzip(string)` / `Typecast.from_gzip(string)` for gzip compression
77+
78+
For outbound HTTP requests, use `Flipper::Adapters::Http::Client` instead of raw `Net::HTTP`. It provides timeouts, retries (`max_retries`), SSL verification, and diagnostic headers (user-agent, client-language, client-platform, etc.). See `lib/flipper/cloud/migrate.rb` for an example.
79+
7280
### Testing
7381

7482
Uses both RSpec (currently preferred for new tests) and Minitest. Shared adapter specs ensure consistency across all storage backends. Extensive testing across multiple Rails versions (5.0-8.0).

lib/flipper/cloud/migrate.rb

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
require "json"
21
require "flipper/adapters/http/client"
32
require "flipper/typecast"
43

@@ -17,18 +16,18 @@ module Cloud
1716
def self.migrate(flipper = Flipper, app_name: nil)
1817
export = flipper.export(format: :json, version: 1)
1918
payload = {
20-
export: JSON.parse(export.contents),
19+
export: Typecast.from_json(export.contents),
2120
metadata: {app_name: app_name},
2221
}
2322

2423
client = build_client("/api")
25-
response = client.post("/migrate", Typecast.to_gzip(JSON.generate(payload)))
26-
body = JSON.parse(response.body) rescue {}
24+
response = client.post("/migrate", Typecast.to_gzip(Typecast.to_json(payload)))
25+
body = Typecast.from_json(response.body) rescue nil
2726

2827
MigrateResult.new(
2928
code: response.code.to_i,
30-
url: body["url"],
31-
message: body["error"],
29+
url: body&.dig("url"),
30+
message: body&.dig("error"),
3231
)
3332
end
3433

@@ -45,12 +44,12 @@ def self.push(token, flipper = Flipper)
4544
"flipper-cloud-token" => token,
4645
})
4746
response = client.post("/import", Typecast.to_gzip(export.contents))
48-
body = JSON.parse(response.body) rescue {}
47+
body = Typecast.from_json(response.body) rescue nil
4948

5049
MigrateResult.new(
5150
code: response.code.to_i,
5251
url: nil,
53-
message: body["error"],
52+
message: body&.dig("error"),
5453
)
5554
end
5655

0 commit comments

Comments
 (0)