indie_flags 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.
- checksums.yaml +7 -0
- data/lib/indie_flags.rb +111 -0
- metadata +45 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 48ad1b3474f96cb021eade2c8f175d23c5c5a103bd016d94e5a499357df74252
|
|
4
|
+
data.tar.gz: 55b3114150143bac53540dd64033e105c45bdda897374cf27cd4b42614246044
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c6de3713329dfa1a23f9e74513731f497f674b06cd85519204ccb25924e9bd91ab6786796d8d0ae3d62ab6e4aee8a7dcb53fa8aeeb4d6b35b4ca793efc711dc2
|
|
7
|
+
data.tar.gz: 0c3bb58577fd781214bc44f82d0d9cb9b85438f570ad1d50e85b07cd40524838a6227f4fc1f0628ca38d326850f1f944378aeb7d07fd7f608620260a562f4012
|
data/lib/indie_flags.rb
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "net/http"
|
|
5
|
+
require "uri"
|
|
6
|
+
|
|
7
|
+
module IndieFlags
|
|
8
|
+
DEFAULT_BASE_URL = "https://api.indieflags.dev"
|
|
9
|
+
DEFAULT_CACHE_TTL_SEC = 60
|
|
10
|
+
|
|
11
|
+
class Client
|
|
12
|
+
def initialize(api_key:, base_url: nil, env: "production", email: nil, cache_ttl_sec: DEFAULT_CACHE_TTL_SEC)
|
|
13
|
+
@api_key = api_key.to_s.strip
|
|
14
|
+
raise ArgumentError, "IndieFlags: api_key is required" if @api_key.empty?
|
|
15
|
+
|
|
16
|
+
@base_url = (base_url || DEFAULT_BASE_URL).to_s.chomp("/")
|
|
17
|
+
@env = (env || "production").to_s.strip.downcase
|
|
18
|
+
@env = "production" if @env.empty?
|
|
19
|
+
@email = email.to_s.strip.empty? ? nil : email.to_s.strip
|
|
20
|
+
@cache_ttl_sec = cache_ttl_sec
|
|
21
|
+
@cache = nil
|
|
22
|
+
@cache_fetched_at = 0
|
|
23
|
+
@mutex = Mutex.new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Fetch all flags and cache. Call once at startup.
|
|
27
|
+
def init
|
|
28
|
+
flags = fetch_all_flags
|
|
29
|
+
if @cache_ttl_sec > 0
|
|
30
|
+
@mutex.synchronize do
|
|
31
|
+
@cache = flags
|
|
32
|
+
@cache_fetched_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
flags
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def enabled?(flag_key)
|
|
39
|
+
get_value(flag_key) == true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def get_value(flag_key)
|
|
43
|
+
key = normalize_key(flag_key)
|
|
44
|
+
cached = get_from_cache
|
|
45
|
+
return cached[key] if cached && cached.key?(key)
|
|
46
|
+
|
|
47
|
+
single = fetch_single_flag(key)
|
|
48
|
+
return single unless single.nil?
|
|
49
|
+
|
|
50
|
+
false
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def invalidate_cache
|
|
54
|
+
@mutex.synchronize { @cache = nil }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def normalize_key(raw)
|
|
60
|
+
raw.to_s.strip.downcase.tr(" ", "").tr("_", "-")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def get_from_cache
|
|
64
|
+
return nil if @cache_ttl_sec <= 0
|
|
65
|
+
|
|
66
|
+
@mutex.synchronize do
|
|
67
|
+
return nil if @cache.nil?
|
|
68
|
+
return nil if (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @cache_fetched_at) > @cache_ttl_sec
|
|
69
|
+
|
|
70
|
+
@cache
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def request(path, query = {})
|
|
75
|
+
uri = URI("#{@base_url}#{path}")
|
|
76
|
+
uri.query = URI.encode_www_form(query) unless query.empty?
|
|
77
|
+
req = Net::HTTP::Get.new(uri)
|
|
78
|
+
req["X-Api-Key"] = @api_key
|
|
79
|
+
req["X-Environment"] = @env
|
|
80
|
+
req["X-Flag-Email"] = @email if @email
|
|
81
|
+
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(req) }
|
|
82
|
+
return nil if res.code == "404"
|
|
83
|
+
|
|
84
|
+
raise "IndieFlags: #{res.code} #{res.body}" unless res.is_a?(Net::HTTPSuccess)
|
|
85
|
+
|
|
86
|
+
JSON.parse(res.body)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def fetch_all_flags
|
|
90
|
+
q = { "apiKey" => @api_key, "env" => @env }
|
|
91
|
+
q["email"] = @email if @email
|
|
92
|
+
data = request("/eval/flags", q)
|
|
93
|
+
return {} unless data
|
|
94
|
+
return {} unless data["flags"].is_a?(Hash)
|
|
95
|
+
|
|
96
|
+
data["flags"].transform_values do |v|
|
|
97
|
+
v.is_a?(String) ? v : !!v
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def fetch_single_flag(flag_key)
|
|
102
|
+
q = { "apiKey" => @api_key, "flag" => flag_key, "env" => @env }
|
|
103
|
+
q["email"] = @email if @email
|
|
104
|
+
data = request("/eval", q)
|
|
105
|
+
return false unless data
|
|
106
|
+
return data["value"] if data.key?("value")
|
|
107
|
+
|
|
108
|
+
data["enabled"] == true
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: indie_flags
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Minimalab
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-02-26 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: is_enabled, get_value, optional 60s cache. Indie Flags API.
|
|
14
|
+
email:
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- lib/indie_flags.rb
|
|
20
|
+
homepage: https://indieflags.minimalab.ai
|
|
21
|
+
licenses:
|
|
22
|
+
- MIT
|
|
23
|
+
metadata:
|
|
24
|
+
source_code_uri: https://github.com/byminimalab/indieflags-api
|
|
25
|
+
documentation_uri: https://indieflags.minimalab.ai/docs
|
|
26
|
+
post_install_message:
|
|
27
|
+
rdoc_options: []
|
|
28
|
+
require_paths:
|
|
29
|
+
- lib
|
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
31
|
+
requirements:
|
|
32
|
+
- - ">="
|
|
33
|
+
- !ruby/object:Gem::Version
|
|
34
|
+
version: '3.0'
|
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
requirements: []
|
|
41
|
+
rubygems_version: 3.0.3.1
|
|
42
|
+
signing_key:
|
|
43
|
+
specification_version: 4
|
|
44
|
+
summary: Feature flags client for Indie Flags
|
|
45
|
+
test_files: []
|