quonfig 0.0.10 → 0.0.12

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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/README.md +94 -0
  4. data/lib/quonfig/caching_http_connection.rb +3 -3
  5. data/lib/quonfig/client.rb +22 -27
  6. data/lib/quonfig/config_loader.rb +5 -1
  7. data/lib/quonfig/config_store.rb +10 -6
  8. data/lib/quonfig/context.rb +5 -4
  9. data/lib/quonfig/datadir.rb +4 -10
  10. data/lib/quonfig/dev_context.rb +4 -2
  11. data/lib/quonfig/duration.rb +2 -2
  12. data/lib/quonfig/encryption.rb +12 -16
  13. data/lib/quonfig/errors/invalid_environment_error.rb +1 -3
  14. data/lib/quonfig/errors/invalid_sdk_key_error.rb +6 -7
  15. data/lib/quonfig/errors/missing_env_var_error.rb +0 -3
  16. data/lib/quonfig/errors/missing_environment_error.rb +1 -1
  17. data/lib/quonfig/errors/uninitialized_error.rb +1 -1
  18. data/lib/quonfig/evaluation.rb +11 -8
  19. data/lib/quonfig/evaluator.rb +34 -37
  20. data/lib/quonfig/fixed_size_hash.rb +1 -0
  21. data/lib/quonfig/http_connection.rb +2 -4
  22. data/lib/quonfig/internal_logger.rb +63 -27
  23. data/lib/quonfig/murmer3.rb +2 -2
  24. data/lib/quonfig/options.rb +62 -75
  25. data/lib/quonfig/periodic_sync.rb +1 -1
  26. data/lib/quonfig/quonfig.rb +3 -3
  27. data/lib/quonfig/reason.rb +2 -1
  28. data/lib/quonfig/resolver.rb +8 -9
  29. data/lib/quonfig/semantic_logger_filter.rb +4 -3
  30. data/lib/quonfig/semver.rb +6 -8
  31. data/lib/quonfig/sse_config_client.rb +14 -15
  32. data/lib/quonfig/stdlib_formatter.rb +3 -3
  33. data/lib/quonfig/telemetry/context_shape_aggregator.rb +2 -3
  34. data/lib/quonfig/telemetry/example_contexts_aggregator.rb +1 -1
  35. data/lib/quonfig/telemetry/telemetry_reporter.rb +1 -0
  36. data/lib/quonfig/time_helpers.rb +2 -0
  37. data/lib/quonfig/version.rb +5 -0
  38. data/lib/quonfig.rb +2 -1
  39. data/quonfig.gemspec +29 -165
  40. metadata +24 -193
  41. data/.claude/rules/constitution.md +0 -81
  42. data/.claude/rules/git-safety.md +0 -11
  43. data/.claude/rules/issue-tracking.md +0 -13
  44. data/.claude/rules/testing-workflow.md +0 -28
  45. data/.envrc.sample +0 -3
  46. data/.github/CODEOWNERS +0 -2
  47. data/.github/pull_request_template.md +0 -8
  48. data/.github/workflows/release.yml +0 -49
  49. data/.github/workflows/ruby.yml +0 -60
  50. data/.github/workflows/test.yaml +0 -40
  51. data/.rubocop.yml +0 -13
  52. data/.tool-versions +0 -1
  53. data/CLAUDE.md +0 -29
  54. data/CODEOWNERS +0 -1
  55. data/Gemfile +0 -26
  56. data/Gemfile.lock +0 -177
  57. data/Rakefile +0 -64
  58. data/VERSION +0 -1
  59. data/dev/allocation_stats +0 -60
  60. data/dev/benchmark +0 -40
  61. data/dev/console +0 -12
  62. data/dev/script_setup.rb +0 -18
  63. data/test/fixtures/datafile.json +0 -87
  64. data/test/integration/test_context_precedence.rb +0 -112
  65. data/test/integration/test_datadir_environment.rb +0 -54
  66. data/test/integration/test_dev_overrides.rb +0 -40
  67. data/test/integration/test_enabled.rb +0 -478
  68. data/test/integration/test_enabled_with_contexts.rb +0 -64
  69. data/test/integration/test_get.rb +0 -136
  70. data/test/integration/test_get_feature_flag.rb +0 -28
  71. data/test/integration/test_get_or_raise.rb +0 -60
  72. data/test/integration/test_get_weighted_values.rb +0 -34
  73. data/test/integration/test_helpers.rb +0 -667
  74. data/test/integration/test_helpers_test.rb +0 -73
  75. data/test/integration/test_post.rb +0 -44
  76. data/test/integration/test_telemetry.rb +0 -170
  77. data/test/support/common_helpers.rb +0 -106
  78. data/test/support/mock_base_client.rb +0 -27
  79. data/test/support/mock_config_loader.rb +0 -1
  80. data/test/test_bound_client.rb +0 -109
  81. data/test/test_caching_http_connection.rb +0 -218
  82. data/test/test_client.rb +0 -255
  83. data/test/test_client_network_mode.rb +0 -136
  84. data/test/test_client_telemetry.rb +0 -175
  85. data/test/test_config_loader.rb +0 -70
  86. data/test/test_context.rb +0 -139
  87. data/test/test_context_shape.rb +0 -37
  88. data/test/test_context_shape_aggregator.rb +0 -126
  89. data/test/test_datadir.rb +0 -203
  90. data/test/test_details_getters.rb +0 -242
  91. data/test/test_dev_context.rb +0 -163
  92. data/test/test_duration.rb +0 -37
  93. data/test/test_encryption.rb +0 -16
  94. data/test/test_evaluation_summaries_aggregator.rb +0 -180
  95. data/test/test_evaluator.rb +0 -285
  96. data/test/test_example_contexts_aggregator.rb +0 -119
  97. data/test/test_exponential_backoff.rb +0 -44
  98. data/test/test_fixed_size_hash.rb +0 -119
  99. data/test/test_helper.rb +0 -17
  100. data/test/test_http_connection.rb +0 -81
  101. data/test/test_internal_logger.rb +0 -34
  102. data/test/test_options.rb +0 -198
  103. data/test/test_rate_limit_cache.rb +0 -44
  104. data/test/test_reason.rb +0 -79
  105. data/test/test_rename.rb +0 -65
  106. data/test/test_resolver.rb +0 -291
  107. data/test/test_semantic_logger_filter.rb +0 -144
  108. data/test/test_semver.rb +0 -108
  109. data/test/test_should_log.rb +0 -186
  110. data/test/test_sse_config_client.rb +0 -297
  111. data/test/test_stdlib_formatter.rb +0 -195
  112. data/test/test_telemetry_reporter.rb +0 -209
  113. data/test/test_typed_getters.rb +0 -131
  114. data/test/test_types.rb +0 -141
  115. data/test/test_weighted_value_resolver.rb +0 -84
@@ -1,136 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # AUTO-GENERATED from integration-test-data/tests/eval/get.yaml.
4
- # Regenerate with:
5
- # cd integration-test-data/generators && npm run generate -- --target=ruby
6
- # Source: integration-test-data/generators/src/targets/ruby.ts
7
- # Do NOT edit by hand — changes will be overwritten.
8
-
9
- require 'test_helper'
10
- require 'integration/test_helpers'
11
-
12
- class TestGet < Minitest::Test
13
- def setup
14
- @store = IntegrationTestHelpers.build_store("get")
15
- end
16
-
17
- # get returns a found value for key
18
- def test_get_returns_a_found_value_for_key
19
- resolver = IntegrationTestHelpers.build_resolver(@store)
20
- IntegrationTestHelpers.assert_resolved(resolver, "my-test-key", {}, "my-test-value")
21
- end
22
-
23
- # get returns nil if value not found
24
- def test_get_returns_nil_if_value_not_found
25
- resolver = IntegrationTestHelpers.build_resolver(@store)
26
- IntegrationTestHelpers.assert_resolved(resolver, "my-missing-key", {}, nil)
27
- end
28
-
29
- # get returns a default for a missing value if a default is given
30
- def test_get_returns_a_default_for_a_missing_value_if_a_default_is_given
31
- resolver = IntegrationTestHelpers.build_resolver(@store)
32
- IntegrationTestHelpers.assert_get_with_default(@store, "my-missing-key", {}, "DEFAULT", "DEFAULT")
33
- end
34
-
35
- # get ignores a provided default if the key is found
36
- def test_get_ignores_a_provided_default_if_the_key_is_found
37
- resolver = IntegrationTestHelpers.build_resolver(@store)
38
- IntegrationTestHelpers.assert_get_with_default(@store, "my-test-key", {}, "DEFAULT", "my-test-value")
39
- end
40
-
41
- # get can return a double
42
- def test_get_can_return_a_double
43
- resolver = IntegrationTestHelpers.build_resolver(@store)
44
- IntegrationTestHelpers.assert_resolved(resolver, "my-double-key", {}, 9.95)
45
- end
46
-
47
- # get can return a string list
48
- def test_get_can_return_a_string_list
49
- resolver = IntegrationTestHelpers.build_resolver(@store)
50
- IntegrationTestHelpers.assert_resolved(resolver, "my-string-list-key", {}, ["a", "b", "c"])
51
- end
52
-
53
- # can return a value provided by an environment variable
54
- def test_can_return_a_value_provided_by_an_environment_variable
55
- resolver = IntegrationTestHelpers.build_resolver(@store)
56
- IntegrationTestHelpers.assert_resolved(resolver, "prefab.secrets.encryption.key", {}, "c87ba22d8662282abe8a0e4651327b579cb64a454ab0f4c170b45b15f049a221")
57
- end
58
-
59
- # can return a value provided by an environment variable after type coercion
60
- def test_can_return_a_value_provided_by_an_environment_variable_after_type_coercion
61
- resolver = IntegrationTestHelpers.build_resolver(@store)
62
- IntegrationTestHelpers.assert_resolved(resolver, "provided.a.number", {}, 1234)
63
- end
64
-
65
- # can decrypt and return a secret value (with decryption key in in env var)
66
- def test_can_decrypt_and_return_a_secret_value_with_decryption_key_in_in_env_var
67
- resolver = IntegrationTestHelpers.build_resolver(@store)
68
- IntegrationTestHelpers.assert_resolved(resolver, "a.secret.config", {}, "hello.world")
69
- end
70
-
71
- # duration 200 ms
72
- def test_duration_200_ms
73
- resolver = IntegrationTestHelpers.build_resolver(@store)
74
- IntegrationTestHelpers.assert_resolved(resolver, "test.duration.PT0.2S", {}, 200)
75
- end
76
-
77
- # duration 90S
78
- def test_duration_90s
79
- resolver = IntegrationTestHelpers.build_resolver(@store)
80
- IntegrationTestHelpers.assert_resolved(resolver, "test.duration.PT90S", {}, 90000)
81
- end
82
-
83
- # duration 1.5M
84
- def test_duration_1_5m
85
- resolver = IntegrationTestHelpers.build_resolver(@store)
86
- IntegrationTestHelpers.assert_resolved(resolver, "test.duration.PT1.5M", {}, 90000)
87
- end
88
-
89
- # duration 0.5H
90
- def test_duration_0_5h
91
- resolver = IntegrationTestHelpers.build_resolver(@store)
92
- IntegrationTestHelpers.assert_resolved(resolver, "test.duration.PT0.5H", {}, 1800000)
93
- end
94
-
95
- # duration test.duration.P1DT6H2M1.5S
96
- def test_duration_test_duration_p1dt6h2m1_5s
97
- resolver = IntegrationTestHelpers.build_resolver(@store)
98
- IntegrationTestHelpers.assert_resolved(resolver, "test.duration.P1DT6H2M1.5S", {}, 108121500)
99
- end
100
-
101
- # json test
102
- def test_json_test
103
- resolver = IntegrationTestHelpers.build_resolver(@store)
104
- IntegrationTestHelpers.assert_resolved(resolver, "test.json", {}, {"a" => 1, "b" => "c"})
105
- end
106
-
107
- # get returns a native json object (not a stringified payload)
108
- def test_get_returns_a_native_json_object_not_a_stringified_payload
109
- resolver = IntegrationTestHelpers.build_resolver(@store)
110
- IntegrationTestHelpers.assert_resolved(resolver, "test.json", {}, {"a" => 1, "b" => "c"})
111
- end
112
-
113
- # list on left side test (1)
114
- def test_list_on_left_side_test_1
115
- resolver = IntegrationTestHelpers.build_resolver(@store)
116
- IntegrationTestHelpers.assert_resolved(resolver, "left.hand.list.test", {"user" => {"name" => "james", "aka" => ["happy", "sleepy"]}}, "correct")
117
- end
118
-
119
- # list on left side test (2)
120
- def test_list_on_left_side_test_2
121
- resolver = IntegrationTestHelpers.build_resolver(@store)
122
- IntegrationTestHelpers.assert_resolved(resolver, "left.hand.list.test", {"user" => {"name" => "james", "aka" => ["a", "b"]}}, "default")
123
- end
124
-
125
- # list on left side test opposite (1)
126
- def test_list_on_left_side_test_opposite_1
127
- resolver = IntegrationTestHelpers.build_resolver(@store)
128
- IntegrationTestHelpers.assert_resolved(resolver, "left.hand.test.opposite", {"user" => {"name" => "james", "aka" => ["happy", "sleepy"]}}, "default")
129
- end
130
-
131
- # list on left side test (3)
132
- def test_list_on_left_side_test_3
133
- resolver = IntegrationTestHelpers.build_resolver(@store)
134
- IntegrationTestHelpers.assert_resolved(resolver, "left.hand.test.opposite", {"user" => {"name" => "james", "aka" => ["a", "b"]}}, "correct")
135
- end
136
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # AUTO-GENERATED from integration-test-data/tests/eval/get_feature_flag.yaml.
4
- # Regenerate with:
5
- # cd integration-test-data/generators && npm run generate -- --target=ruby
6
- # Source: integration-test-data/generators/src/targets/ruby.ts
7
- # Do NOT edit by hand — changes will be overwritten.
8
-
9
- require 'test_helper'
10
- require 'integration/test_helpers'
11
-
12
- class TestGetFeatureFlag < Minitest::Test
13
- def setup
14
- @store = IntegrationTestHelpers.build_store("get_feature_flag")
15
- end
16
-
17
- # get returns the underlying value for a feature flag
18
- def test_get_returns_the_underlying_value_for_a_feature_flag
19
- resolver = IntegrationTestHelpers.build_resolver(@store)
20
- IntegrationTestHelpers.assert_resolved(resolver, "feature-flag.integer", {}, 3)
21
- end
22
-
23
- # get returns the underlying value for a feature flag that matches the highest precedent rule
24
- def test_get_returns_the_underlying_value_for_a_feature_flag_that_matches_the_highest_precedent_rule
25
- resolver = IntegrationTestHelpers.build_resolver(@store)
26
- IntegrationTestHelpers.assert_resolved(resolver, "feature-flag.integer", {"user" => {"key" => "michael"}}, 5)
27
- end
28
- end
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # AUTO-GENERATED from integration-test-data/tests/eval/get_or_raise.yaml.
4
- # Regenerate with:
5
- # cd integration-test-data/generators && npm run generate -- --target=ruby
6
- # Source: integration-test-data/generators/src/targets/ruby.ts
7
- # Do NOT edit by hand — changes will be overwritten.
8
-
9
- require 'test_helper'
10
- require 'integration/test_helpers'
11
-
12
- class TestGetOrRaise < Minitest::Test
13
- def setup
14
- @store = IntegrationTestHelpers.build_store("get_or_raise")
15
- end
16
-
17
- # get_or_raise can raise an error if value not found
18
- def test_get_or_raise_can_raise_an_error_if_value_not_found
19
- resolver = IntegrationTestHelpers.build_resolver(@store)
20
- ctx = Quonfig::Context.new({})
21
- assert_raises(Quonfig::Errors::MissingDefaultError) { resolver.get("my-missing-key", ctx) }
22
- end
23
-
24
- # get_or_raise returns a default value instead of raising
25
- def test_get_or_raise_returns_a_default_value_instead_of_raising
26
- resolver = IntegrationTestHelpers.build_resolver(@store)
27
- IntegrationTestHelpers.assert_get_with_default(@store, "my-missing-key", {}, "DEFAULT", "DEFAULT")
28
- end
29
-
30
- # get_or_raise raises the correct error if it doesn't raise on init timeout
31
- def test_get_or_raise_raises_the_correct_error_if_it_doesn_t_raise_on_init_timeout
32
- IntegrationTestHelpers.assert_client_construction_raises("any-key", 0.01, "https://app.staging-prefab.cloud", "return", "get_or_raise", Quonfig::Errors::MissingDefaultError)
33
- end
34
-
35
- # get_or_raise can raise an error if the client does not initialize in time
36
- def test_get_or_raise_can_raise_an_error_if_the_client_does_not_initialize_in_time
37
- IntegrationTestHelpers.assert_initialization_timeout_error("any-key", 0.01, "https://app.staging-prefab.cloud", "raise")
38
- end
39
-
40
- # raises an error if a config is provided by a missing environment variable
41
- def test_raises_an_error_if_a_config_is_provided_by_a_missing_environment_variable
42
- resolver = IntegrationTestHelpers.build_resolver(@store)
43
- ctx = Quonfig::Context.new({})
44
- assert_raises(Quonfig::Errors::MissingEnvVarError) { resolver.get("provided.by.missing.env.var", ctx) }
45
- end
46
-
47
- # raises an error if an env-var-provided config cannot be coerced to configured type
48
- def test_raises_an_error_if_an_env_var_provided_config_cannot_be_coerced_to_configured_type
49
- resolver = IntegrationTestHelpers.build_resolver(@store)
50
- ctx = Quonfig::Context.new({})
51
- assert_raises(Quonfig::Errors::EnvVarParseError) { resolver.get("provided.not.a.number", ctx) }
52
- end
53
-
54
- # raises an error for decryption failure
55
- def test_raises_an_error_for_decryption_failure
56
- resolver = IntegrationTestHelpers.build_resolver(@store)
57
- ctx = Quonfig::Context.new({})
58
- assert_raises(Quonfig::Errors::DecryptionError) { resolver.get("a.broken.secret.config", ctx) }
59
- end
60
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # AUTO-GENERATED from integration-test-data/tests/eval/get_weighted_values.yaml.
4
- # Regenerate with:
5
- # cd integration-test-data/generators && npm run generate -- --target=ruby
6
- # Source: integration-test-data/generators/src/targets/ruby.ts
7
- # Do NOT edit by hand — changes will be overwritten.
8
-
9
- require 'test_helper'
10
- require 'integration/test_helpers'
11
-
12
- class TestGetWeightedValues < Minitest::Test
13
- def setup
14
- @store = IntegrationTestHelpers.build_store("get_weighted_values")
15
- end
16
-
17
- # weighted value is consistent 1
18
- def test_weighted_value_is_consistent_1
19
- resolver = IntegrationTestHelpers.build_resolver(@store)
20
- IntegrationTestHelpers.assert_resolved(resolver, "feature-flag.weighted", {"user" => {"tracking_id" => "a72c15f5"}}, 1)
21
- end
22
-
23
- # weighted value is consistent 2
24
- def test_weighted_value_is_consistent_2
25
- resolver = IntegrationTestHelpers.build_resolver(@store)
26
- IntegrationTestHelpers.assert_resolved(resolver, "feature-flag.weighted", {"user" => {"tracking_id" => "92a202f2"}}, 2)
27
- end
28
-
29
- # weighted value is consistent 3
30
- def test_weighted_value_is_consistent_3
31
- resolver = IntegrationTestHelpers.build_resolver(@store)
32
- IntegrationTestHelpers.assert_resolved(resolver, "feature-flag.weighted", {"user" => {"tracking_id" => "8f414100"}}, 3)
33
- end
34
- end