typed-config 1.3.8

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3551b257563c33aefb5d1da190ddc584bfb1893edc271c775d82ab3fe46c30f1
4
+ data.tar.gz: 2a7b822b9d3e22c2e4c678f4e00dd5b3618eb5d51ecd8210ff1af60c35f74d10
5
+ SHA512:
6
+ metadata.gz: 1c0477d6708d339e692e504503685d4757a4d00d36b968d385cf920006993b70e529a99413b8ac958ebf9bbb15ca31bab86a80decf672aca17944f4f8089f45b
7
+ data.tar.gz: 12cc17789e2b9531a8dc05f8770c53dd0f5005af125351dd8833606137931f6a7d5615e752f84a4ea473023992f72f4dcdcda4aa16b4c95907ff2b36367c28af
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
@@ -0,0 +1,109 @@
1
+ # TypedConfig
2
+
3
+ TypedConfig is a simple solution for managing multi-environment application
4
+ settings whilst maintaining type safety.
5
+
6
+ Currently, only Rails is supported out of the box.
7
+
8
+ TypedConfig is meant to run in projects using [Sorbet](https://sorbet.org/),
9
+ although it can run in projects not using it and still gain from the easy-to-configure
10
+ settings.
11
+
12
+ This project has been inspired by [Config](https://github.com/rubyconfig/config) and
13
+ it's meant to be an easy drop-in replacement with type-safety.
14
+
15
+ ## Installing
16
+
17
+ Add the gem to your `Gemfile`:
18
+ ```ruby
19
+ gem 'typed-config'
20
+ ```
21
+
22
+ Run the install rake task to initialize the config schema and settings files:
23
+ ```ruby
24
+ rails g typed_config:install
25
+ ```
26
+
27
+ This will generate the schema file `config/config.rb` where the schema of the
28
+ settings should be defined, and the settings file:
29
+ ```
30
+ config/settings.yml
31
+ config/settings.local.yml
32
+ config/settings/development.yml
33
+ config/settings/production.yml
34
+ config/settings/test.yml
35
+ ```
36
+ It will also update the existing `.gitignore` to local settings files.
37
+
38
+ ## Defining the Settings Properties
39
+ First, the schema of the Settings object must be defined in the `config/config.rb`
40
+ file, for example:
41
+ ```ruby
42
+ TypedConfig::Schema.configure do |s|
43
+ s.const :env, String
44
+ s.const :app do
45
+ s.const :domain, T.nilable(String)
46
+ s.const :port, T.nilable(Integer)
47
+ end
48
+ s.const :support do
49
+ s.const :email, String
50
+ end
51
+ end
52
+ ```
53
+
54
+ Now in the code, you can access any properties as a `T::Struct`. All properties will be
55
+ available across the application in a `Settings` object:
56
+ ```ruby
57
+ Settings.env
58
+ Settting.support.email
59
+
60
+ # Example:
61
+ config.action_mailer.asset_host = "https://#{Settings.app.domain}"
62
+ ```
63
+
64
+ ## Changing the Settings
65
+ The settings are defined in YAML (with ERB support). Once the schema is defined, update
66
+ one of the settings file to load the data:
67
+ ```yaml
68
+ env: <%= ENV['RACK_ENV'] %>
69
+ app:
70
+ domain: <%= ENV['APP_DOMAIN'] %>
71
+ port: <%= ENV.fetch('APP_PORT', 3000) %>
72
+ support:
73
+ email: 'support@typed-config.com
74
+ ```
75
+ When loaded, `typed-config` will try to automatically coerce the values to match the ones
76
+ specified in the schema.
77
+
78
+ You may define default (or different) settings for each environment by changing the
79
+ `config/settings/#{env}.yml`. For instance, to have different defaults in the test
80
+ environment, add the settings to `config/settings/test.yml`.
81
+
82
+ In order from top to bottom - the settings in the lower files overwrite the ones higher -
83
+ these are the files loaded:
84
+ ```
85
+ config/settings.yml
86
+ config/settings/#{environment}.yml
87
+
88
+ config/settings.local.yml
89
+ config/settings/#{environment}.local.yml
90
+ ```
91
+
92
+ ## Type Safety
93
+ To make use of the type-safety feature, you must re-generate the RBI files when the schema
94
+ is changed using a rake command:
95
+ ```shell
96
+ bundle exec rake typed-config:rbi
97
+ ```
98
+
99
+ Now you can run sorbet to check the types of the settings properties:
100
+ ```ruby
101
+ T.reveal_type(Settings.app.domain) # Revealed type: T.nilable(String)
102
+
103
+ sig { params(server_write_key: String).void }
104
+ def configure_segment(server_write_key); end
105
+
106
+
107
+ configure_segment(server_write_key: Settings.segment.server_write_key)
108
+ # Expected String but found T.nilable(String) for argument server_write_key
109
+ ```
@@ -0,0 +1,36 @@
1
+ # typed: ignore
2
+ # frozen_string_literal: true
3
+
4
+ module TypedConfig
5
+ module Generators
6
+ class InstallGenerator < ::Rails::Generators::Base
7
+ desc 'Generated typed-config files for Rails.'
8
+
9
+ source_root File.expand_path('templates', __dir__)
10
+
11
+ def copy_config
12
+ template 'config.rb', 'config/config.rb'
13
+ end
14
+
15
+ def copy_settings
16
+ template 'settings.yml', 'config/settings.yml'
17
+ template 'settings.local.yml', 'config/settings.local.yml'
18
+ directory 'settings', 'config/settings'
19
+ end
20
+
21
+ def modify_gitignore
22
+ create_file '.gitignore' unless File.file?('.gitignore')
23
+
24
+ append_to_file '.gitignore' do
25
+ "\nconfig/settings.local.yml\n" \
26
+ "config/settings/*.local.yml\n" \
27
+ "config/environments/*.local.yml\n"
28
+ end
29
+ end
30
+
31
+ def generate_rbi
32
+ rake 'typed-config:rbi'
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,9 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ TypedConfig::Schema.configure do |s|
5
+ s.const :aws do
6
+ s.const :access_key_id, T.nilable(String)
7
+ s.const :secret_access_key, T.nilable(String)
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ aws:
2
+ access_key_id: test-access-key-id
3
+ secret_access_key: test-secret-access-key
@@ -0,0 +1,3 @@
1
+ aws:
2
+ access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
3
+ secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
@@ -0,0 +1,10 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'sorbet-runtime'
5
+
6
+ require 'typed_config/version'
7
+ require 'typed_config/setup'
8
+ require 'typed_config/schema'
9
+
10
+ require('typed_config/railtie') if defined?(::Rails)
@@ -0,0 +1,20 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'erb'
5
+ require 'yaml'
6
+
7
+ module TypedConfig
8
+ class Loader
9
+ extend T::Sig
10
+
11
+ sig { params(filename: String).returns(T::Hash[String, T.untyped]) }
12
+ def load(filename)
13
+ return {} unless File.file?(filename)
14
+
15
+ contents = File.read(filename)
16
+ yaml = YAML.safe_load(ERB.new(contents).result) || {}
17
+ T.cast(yaml, T::Hash[String, T.untyped])
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'setup'
5
+
6
+ module TypedConfig
7
+ class Railtie < ::Rails::Railtie
8
+ railtie_name :typed_config
9
+
10
+ rake_tasks do
11
+ path = File.expand_path(__dir__)
12
+ Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
13
+ end
14
+
15
+ def preload
16
+ Setup.new.call(
17
+ config_path: ::Rails.root.join('config'),
18
+ env: ::Rails.env,
19
+ )
20
+ end
21
+
22
+ config.before_configuration { T.unsafe(self).preload }
23
+ end
24
+ end
@@ -0,0 +1,50 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'erb'
5
+
6
+ module TypedConfig
7
+ class RBIBuilder
8
+ extend T::Sig
9
+
10
+ sig { void }
11
+ def initialize
12
+ @structs = T.let(
13
+ {},
14
+ T::Hash[
15
+ String,
16
+ T::Array[{ name: Symbol, type: String }],
17
+ ],
18
+ )
19
+ end
20
+
21
+ sig { params(struct: Class).void }
22
+ def add_struct(struct)
23
+ @structs[T.must(struct.name)] ||= []
24
+ end
25
+
26
+ sig { params(struct: Class, name: Symbol, type: T.untyped).void }
27
+ def add_const(struct, name, type)
28
+ add_struct(struct)
29
+ T.must(@structs[T.must(struct.name)]).push({ name: name, type: type.name })
30
+ end
31
+
32
+ sig { params(schema_const_name: String).returns(String) }
33
+ def build(schema_const_name)
34
+ b = binding
35
+ b.local_variable_set(:schema_const_name, schema_const_name)
36
+ b.local_variable_set(:structs, @structs)
37
+ template_file = File.read(File.join(File.dirname(__FILE__), 'structs.rbi.erb'))
38
+ ERB.new(template_file, trim_mode: '>').result(b)
39
+ end
40
+
41
+ private
42
+
43
+ sig { params(consts: T::Array[{ name: Symbol, type: String }]).returns(String) }
44
+ def build_consts(consts)
45
+ consts.inject('') do |prev, const|
46
+ prev + " const :#{const[:name]}, #{const[:type]}\n"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,42 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require_relative './schema_builder'
5
+ require_relative './structs/_structs'
6
+
7
+ module TypedConfig
8
+ class Schema
9
+ @schema_builder = T.let(nil, T.nilable(SchemaBuilder))
10
+ @schema_const_name = T.let('Settings', String)
11
+
12
+ class << self
13
+ extend T::Sig
14
+
15
+ sig { returns(String) }
16
+ attr_reader :schema_const_name
17
+
18
+ sig do
19
+ params(
20
+ const_name: T.nilable(String),
21
+ _blk: T.proc.params(config: SchemaBuilder).void,
22
+ ).void
23
+ end
24
+ def configure(const_name = nil, &_blk)
25
+ @schema_const_name = const_name || schema_const_name
26
+ yield schema_builder
27
+ end
28
+
29
+ sig { returns(String) }
30
+ def rbi
31
+ schema_builder.build_rbi(schema_const_name)
32
+ end
33
+
34
+ private
35
+
36
+ sig { returns(SchemaBuilder) }
37
+ def schema_builder
38
+ @schema_builder ||= SchemaBuilder.new('Settings')
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,77 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require_relative './rbi_builder'
5
+ require_relative './structs/_structs'
6
+
7
+ module TypedConfig
8
+ class SchemaBuilder
9
+ extend T::Sig
10
+
11
+ sig { params(struct: String, rbi_builder: RBIBuilder).void }
12
+ def initialize(struct, rbi_builder: RBIBuilder.new)
13
+ @rbi_builder = rbi_builder
14
+ @struct = T.let(create_struct(Structs, struct), Class)
15
+ end
16
+
17
+ sig do
18
+ params(
19
+ name: Symbol,
20
+ type: T.untyped,
21
+ blk: T.nilable(T.proc.void),
22
+ ).void
23
+ end
24
+ def const(name, type = nil, &blk)
25
+ clazz = retrieve_class(name: name, type: type, &blk)
26
+ raise ArgumentError, "Attribute '#{name}' must receive a type or block." if clazz.nil?
27
+
28
+ rbi_builder.add_const(struct, name, clazz)
29
+ struct.tap do |scope|
30
+ scope.const name, clazz
31
+ end
32
+ end
33
+
34
+ sig { params(schema_const_name: String).returns(String) }
35
+ def build_rbi(schema_const_name)
36
+ rbi_builder.build(schema_const_name)
37
+ end
38
+
39
+ protected
40
+
41
+ sig { returns(Class) }
42
+ attr_reader :struct
43
+
44
+ sig { returns(RBIBuilder) }
45
+ attr_reader :rbi_builder
46
+
47
+ sig do
48
+ params(
49
+ name: Symbol,
50
+ type: T.untyped,
51
+ blk: T.nilable(T.proc.void),
52
+ ).returns(T.untyped)
53
+ end
54
+ def retrieve_class(name:, type:, &blk)
55
+ return type unless block_given?
56
+
57
+ process_substruct(name: name, &blk)
58
+ end
59
+
60
+ sig { params(name: Symbol, blk: T.proc.void).returns(Class) }
61
+ def process_substruct(name:, &blk)
62
+ top_struct = struct
63
+ sub_struct = create_struct(struct, name.to_s)
64
+ @struct = sub_struct
65
+ instance_eval(&blk)
66
+ @struct = top_struct
67
+ sub_struct
68
+ end
69
+
70
+ sig { params(base: T.any(Module, Class), name: String).returns(Class) }
71
+ def create_struct(base, name)
72
+ new_struct = base.const_set(name.camelcase, Class.new(T::Struct))
73
+ rbi_builder.add_struct(new_struct)
74
+ new_struct
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,55 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'sorbet-coerce'
5
+ require_relative './loader'
6
+ require_relative './schema'
7
+
8
+ module TypedConfig
9
+ class Setup
10
+ extend T::Sig
11
+
12
+ sig { params(loader: Loader).void }
13
+ def initialize(loader: Loader.new)
14
+ @loader = loader
15
+ end
16
+
17
+ sig { params(config_path: T.any(Pathname, String), env: String).void }
18
+ def call(config_path:, env: T.cast(ENV['RACK_ENV'], String))
19
+ config_file = "#{config_path}/config.rb"
20
+ return unless File.file?(config_file)
21
+
22
+ require_relative config_file
23
+
24
+ settings = build_settings(config_path: config_path, env: env)
25
+ definition = TypeCoerce[Structs::Settings].new.from(settings)
26
+ Object.const_set(Schema.schema_const_name, definition)
27
+ end
28
+
29
+ private
30
+
31
+ sig { returns(Loader) }
32
+ attr_reader :loader
33
+
34
+ sig do
35
+ params(config_path: T.any(Pathname, String), env: String)
36
+ .returns(T::Hash[String, T.untyped])
37
+ end
38
+ def build_settings(config_path:, env:)
39
+ merge_settings([
40
+ loader.load("#{config_path}/settings.yml"),
41
+ loader.load("#{config_path}/settings/#{env}.yml"),
42
+ loader.load("#{config_path}/settings.local.yml"),
43
+ loader.load("#{config_path}/settings/#{env}.local.yml"),
44
+ ])
45
+ end
46
+
47
+ sig do
48
+ params(values: T::Array[T::Hash[String, T.untyped]])
49
+ .returns(T::Hash[String, T.untyped])
50
+ end
51
+ def merge_settings(values)
52
+ values.inject({}) { |prev, curr| prev.deep_merge(curr) }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,12 @@
1
+ # typed: strong
2
+
3
+ ::<%= schema_const_name %> = T.let(nil, TypedConfig::Structs::Settings)
4
+ <% structs.each do |struct_name, consts| %>
5
+
6
+ class <%= struct_name %> < T::Struct
7
+ <% consts.each do |const| %>
8
+ const :<%= const[:name] %>, <%= const[:type] %>
9
+
10
+ <% end %>
11
+ end
12
+ <% end %>
@@ -0,0 +1,7 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ module TypedConfig
5
+ module Structs
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ module TypedConfig
5
+ module Structs
6
+ class Settings < T::Struct
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ namespace 'typed-config' do
5
+ task rbi: :environment do
6
+ puts 'Generating RBI files...'
7
+ rbi = TypedConfig::Schema.rbi
8
+ FileUtils.mkdir_p(::Rails.root.join('sorbet', 'typed-config'))
9
+ File.write(::Rails.root.join('sorbet', 'typed-config', 'structs.rbi'), rbi)
10
+ puts 'RBI files updated in sorbet/typed-config.'
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ # typed: strong
2
+ # frozen_string_literal: true
3
+
4
+ module TypedConfig
5
+ VERSION = '1.3.8'
6
+ end
@@ -0,0 +1,15 @@
1
+ # typed: strong
2
+
3
+ module TypedConfig
4
+ class Schema
5
+ extend T::Sig
6
+
7
+ sig do
8
+ params(
9
+ const_name: T.nilable(String),
10
+ blk: T.proc.params(config: SchemaBuilder).void,
11
+ ).void
12
+ end
13
+ def self.configure(const_name = nil, &blk); end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # typed: strong
2
+
3
+ module TypedConfig
4
+ class SchemaBuilder
5
+ extend T::Sig
6
+
7
+ sig do
8
+ params(
9
+ name: Symbol,
10
+ type: T.untyped,
11
+ blk: T.nilable(T.proc.void),
12
+ ).void
13
+ end
14
+ def const(name, type = nil, &blk); end
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: typed-config
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.8
5
+ platform: ruby
6
+ authors:
7
+ - Alex Santos
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: deep_merge
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.2.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.2.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: sorbet-coerce
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0.2'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0.2'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rails
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 5.2.4
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 5.2.4
61
+ - !ruby/object:Gem::Dependency
62
+ name: rubocop
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 0.84.0
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 0.84.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: rubocop-performance
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 1.6.1
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 1.6.1
89
+ - !ruby/object:Gem::Dependency
90
+ name: rubocop-sorbet
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 0.4.0
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 0.4.0
103
+ - !ruby/object:Gem::Dependency
104
+ name: rubocop-rspec
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: 1.39.0
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: 1.39.0
117
+ - !ruby/object:Gem::Dependency
118
+ name: sorbet-runtime
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ description: Manage multi-environment settings with type-safety in Ruby
132
+ email: hello@alexcsantos.com
133
+ executables: []
134
+ extensions: []
135
+ extra_rdoc_files: []
136
+ files:
137
+ - Gemfile
138
+ - README.md
139
+ - lib/generators/typed_config/install_generator.rb
140
+ - lib/generators/typed_config/templates/config.rb
141
+ - lib/generators/typed_config/templates/settings.local.yml
142
+ - lib/generators/typed_config/templates/settings.yml
143
+ - lib/generators/typed_config/templates/settings/development.yml
144
+ - lib/generators/typed_config/templates/settings/production.yml
145
+ - lib/generators/typed_config/templates/settings/test.yml
146
+ - lib/typed-config.rb
147
+ - lib/typed_config/loader.rb
148
+ - lib/typed_config/railtie.rb
149
+ - lib/typed_config/rbi_builder.rb
150
+ - lib/typed_config/schema.rb
151
+ - lib/typed_config/schema_builder.rb
152
+ - lib/typed_config/setup.rb
153
+ - lib/typed_config/structs.rbi.erb
154
+ - lib/typed_config/structs/_structs.rb
155
+ - lib/typed_config/structs/settings.rbi
156
+ - lib/typed_config/tasks/typed-config/rbi.rake
157
+ - lib/typed_config/version.rb
158
+ - rbi/schema.rbi
159
+ - rbi/schema_builder.rbi
160
+ homepage: https://rubygems.org/gems/typed-config
161
+ licenses:
162
+ - MIT
163
+ metadata: {}
164
+ post_install_message:
165
+ rdoc_options: []
166
+ require_paths:
167
+ - lib
168
+ required_ruby_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: 2.4.0
173
+ required_rubygems_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ requirements: []
179
+ rubygems_version: 3.0.6
180
+ signing_key:
181
+ specification_version: 4
182
+ summary: Type-safe settings for Rails
183
+ test_files: []