configsl 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9cf52e102562625f71dabce8ff0f05d8d1a0d129e62584a80aae1abd4903585d
4
+ data.tar.gz: f59fcc77eb986087131fe84e6770bc667be007ef922cb77477ab54b840e1a75b
5
+ SHA512:
6
+ metadata.gz: 49f9b7c79beae87c9aff4be256de82fafa0f5fe6e76f6243f48c25ded6c0363df8330874ddcb6b7f7719ed2fd9d5ea02d4598491acb1d359c151656d25f060fe
7
+ data.tar.gz: afec6d65e82afe81485aa89bf73878e1d95deb96dc04db343edbb9cec980332738743208994a3d57ee2bedfd8f69f124187c134d3fb137a83ee7581920b2eb4b
data/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog][changelog], and this project adheres
6
+ to [Semantic Versioning][versioning].
7
+ ß
8
+ ## 1.0.0
9
+
10
+ Initial release.
11
+
12
+ ### Added
13
+
14
+ - Simple DSL for defining configuration
15
+ - JSON and YAML file reading support
16
+ - Environment variable reading support
17
+ - Formatting and validation of values
18
+
19
+ [changelog]: https://keepachangelog.com/en/1.1.0/
20
+ [versioning]: https://semver.org/spec/v2.0.0.html
data/Gemfile ADDED
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ group :development do
8
+ gem 'rake', '~> 13.2'
9
+ gem 'rubocop', '~> 1.65'
10
+ gem 'rubocop-factory_bot', '~> 2.26'
11
+ gem 'rubocop-rake', '~> 0.6'
12
+ gem 'rubocop-rspec', '~> 3.0'
13
+ end
14
+
15
+ group :test do
16
+ # activesupport 7.2 introduces a breaking change that causes the specs to
17
+ # fail.
18
+ gem 'activesupport', '~> 7.1.0'
19
+
20
+ gem 'coveralls_reborn', '~> 0.28'
21
+ gem 'factory_bot', '~> 6.4'
22
+ gem 'rspec', '~> 3.13'
23
+ gem 'rspec-github', '~> 2.4'
24
+ gem 'simplecov', '~> 0.22'
25
+ end
data/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # ConfigSL [![Coverage Status][badge-coverage]][coverage]
2
+
3
+ ConfigSL is a simple Domain-Specific Language (DSL) module for configuration.
4
+ It is designed to provide a declarative way to define configuration, with as few
5
+ dependencies and additional cruft as possible. It is both modular and
6
+ extensible, so you can use as little or as much as you need.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'configsl'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ ```sh
19
+ bundle install
20
+ ```
21
+
22
+ Or install it yourself as:
23
+
24
+ ```sh
25
+ gem install configsl
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ You can start defining your configurations using two methods:
31
+
32
+ 1. Extend the included `ConfigSL::Config` base class
33
+ 2. Include the `ConfigSL` modules you want to use in you class
34
+
35
+ ### Using the included base class
36
+
37
+ The `ConfigSL::Config` base class includes common functionality for working with
38
+ configurations. Currently, the class provides the following features:
39
+
40
+ - **DSL**: The primary DSL for defining configuration options
41
+ - **Format**: A simple way to enforce option value formatting
42
+ - **FromEnvironment**: Load configuration from environment variables
43
+ - **FromFile**: Load configuration from a file
44
+ - **Validation**: Built-in validation for configuration options
45
+
46
+ ```ruby
47
+ require 'configsl'
48
+
49
+ class AppConfig < ConfigSL::Config
50
+ register_file_format :json
51
+ register_file_format :yaml
52
+
53
+ option :name, type: String, default: 'My App'
54
+ option :environment, type: Symbol, enum: %i[dev test prod], default: :dev,
55
+ env_variable: 'RACK_ENV'
56
+ option :database, type: DatabaseConfig, required: true
57
+ end
58
+ ```
59
+
60
+ ### Including modules
61
+
62
+ If you'd like to pick and choose the features you want to use, you can include
63
+ modules individually. _Most_ modules can be included in any order, but the `DSL`
64
+ module _**must**_ be included before any others.
65
+
66
+ Additionally, you will need to implement `initialize` -- or some other method --
67
+ that sets the configuration values by calling `set_value` for each option.
68
+
69
+ ```ruby
70
+ require 'configsl'
71
+
72
+ class ApplicationConfig
73
+ include ConfigSL::DSL
74
+ include ConfigSL::Format
75
+ include ConfigSL::FromEnvironment
76
+
77
+ option :name, type: String, default: 'My App'
78
+ option :environment, type: Symbol, env_variable: 'RACK_ENV'
79
+ option :database, type: DatabaseConfig
80
+
81
+ def initialize(params = {})
82
+ params.each do |name, value|
83
+ set_value(name, value)
84
+ end
85
+ end
86
+ end
87
+ ```
88
+
89
+ ### A note about inheritance
90
+
91
+ When working with multiple configuration classes, you'll likely want to use a
92
+ base class. This could be the `ConfigSL::Config` class, or a custom class that
93
+ includes the modules you need.
94
+
95
+ While the modules you include are inherited by subclasses, any options you
96
+ define via DSL are not. This is because these values are stored using _class
97
+ instance variables_. As a result, if you have options that are shared between
98
+ classes, they will need to be implemented in both.
99
+
100
+ It's important to note that this is not limited to your defined configuration
101
+ options, but also methods such as `register_file_format` and
102
+ `config_file_path`.
103
+
104
+ [badge-coverage]: https://coveralls.io/repos/github/jamesiarmes/configsl/badge.svg
105
+ [coverage]: https://coveralls.io/github/jamesiarmes/configsl
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'dsl'
4
+ require_relative 'file_format/json'
5
+ require_relative 'file_format/yaml'
6
+ require_relative 'format'
7
+ require_relative 'from_environment'
8
+ require_relative 'from_file'
9
+ require_relative 'validation'
10
+
11
+ module ConfigSL
12
+ # Base class for configuration that includes common functionality.
13
+ class Config
14
+ include DSL
15
+ include Format
16
+ include FromEnvironment
17
+ include FromFile
18
+ include Validation
19
+
20
+ def initialize(params = {})
21
+ params.each do |name, value|
22
+ set_value(name, value)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'exception'
4
+
5
+ module ConfigSL
6
+ # DSL (Domain Specific Language) for defining configuration options.
7
+ #
8
+ # This module provides the base functionality for building configuration
9
+ # classes. It should be included before any other modules that provide
10
+ # additional functionality, such as formatting or validation.
11
+ #
12
+ # The class that includes this module will need to set the values for the
13
+ # options before they can be used. The easiest way to do this is to call
14
+ # `set_value` with each option and its value in the constructor.
15
+ #
16
+ # @example
17
+ # def initialize(params = {})
18
+ # params.each do |name, value|
19
+ # set_value(name, value)
20
+ # end
21
+ # end
22
+ module DSL
23
+ # Include the class methods when the module is included.
24
+ def self.included(base)
25
+ base.extend ClassMethods
26
+ end
27
+
28
+ # Returns the options hash for the class of the current instance.
29
+ #
30
+ # @return [Hash] The options hash.
31
+ def options
32
+ self.class.options
33
+ end
34
+
35
+ # Returns the values of all the options.
36
+ #
37
+ # @return [Array<Hash>] The values of all the options.
38
+ def values
39
+ options.each_key.to_h { |name| [name, get_value(name)] }
40
+ end
41
+
42
+ private
43
+
44
+ # Gets the value of an option.
45
+ #
46
+ # If the option is not set, it will return the default value.
47
+ #
48
+ # @param name [Symbol] The name of the option.
49
+ # @return [Object] The value of the option.
50
+ #
51
+ # @raise [InvalidOptionError] If the option is not defined.
52
+ def get_value(name)
53
+ raise InvalidOptionError, "Option #{name} is not defined" unless options.key?(name)
54
+
55
+ @params.fetch(name, options[name]&.[](:default))
56
+ end
57
+
58
+ # Sets the value of an option.
59
+ #
60
+ # @param name [Symbol] The name of the option.
61
+ # @param value [Object] The value to set.
62
+ # @return [Object] The value that was set for the option.
63
+ #
64
+ # @raise [InvalidOptionError] If the option is not defined.
65
+ def set_value(name, value)
66
+ raise InvalidOptionError, "Option #{name} is not defined" unless options.key?(name)
67
+
68
+ @params ||= {}
69
+ @params[name] = value
70
+ end
71
+
72
+ # Required class methods for the config DSL.
73
+ module ClassMethods
74
+ # Define an option for the class.
75
+ #
76
+ # The keys for the options hash will vary depending on the modules that
77
+ # have been included in your class.
78
+ #
79
+ # @param name [Symbol] The name of the option.
80
+ # @param opts [Hash] The options for the option.
81
+ # @return [void]
82
+ def option(name, opts = {})
83
+ options.merge!({ name => opts })
84
+ define_method(name) { get_value(name) }
85
+ end
86
+
87
+ # Returns the options hash for the class.
88
+ #
89
+ # @return [Hash] The options hash.
90
+ def options
91
+ @options ||= {}
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigSL
4
+ class InvalidOptionError < ArgumentError; end
5
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigSL
4
+ module FileFormat
5
+ # Base class for file format support.
6
+ #
7
+ # @abstract Subclass and override `#read` and `.extensions` to implement a
8
+ # file format.
9
+ class Base
10
+ def initialize(file)
11
+ @file = file
12
+ end
13
+
14
+ # Extensions used to identify the file format.
15
+ #
16
+ # Values should be returned in order of preference.
17
+ #
18
+ # @return [Array<Symbol>] The extensions used to identify the file format.
19
+ def self.extensions
20
+ []
21
+ end
22
+
23
+ # Reads the file and returns a hash of configuration values.
24
+ #
25
+ # @return [Hash{Symbol => Object}]
26
+ #
27
+ # @raise [NotImplementedError] If not implemented.
28
+ def read
29
+ raise NotImplementedError, 'Not implemented'
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ require_relative 'base'
6
+
7
+ module ConfigSL
8
+ module FileFormat
9
+ # Support for JSON files.
10
+ class Json < Base
11
+ def self.extensions
12
+ %i[json]
13
+ end
14
+
15
+ def read
16
+ ::JSON.parse(File.read(@file), symbolize_names: true).each do |name, value|
17
+ yield name, value if block_given?
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ require_relative 'base'
6
+
7
+ module ConfigSL
8
+ module FileFormat
9
+ # Support for YAML files.
10
+ class Yaml < Base
11
+ def self.extensions
12
+ %i[yaml yml]
13
+ end
14
+
15
+ def read
16
+ ::YAML.load_file(@file, symbolize_names: true).each do |name, value|
17
+ yield name, value if block_given?
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigSL
4
+ class FileFormatError < ArgumentError; end
5
+ class FileNotFoundError < ArgumentError; end
6
+
7
+ # Support for common file operations.
8
+ #
9
+ # This module provides limited functionality itself, but instead provides
10
+ # basic support for configuration files that is leveraged by other modules.
11
+ #
12
+ # Including this modules adds the following DSL methods to your class:
13
+ #
14
+ # - config_file_path: Set the default path to look for configuration files
15
+ # - config_file_name: Set the default file name to look for configuration
16
+ # files, without extension
17
+ # - register_file_format: Add support for a file format
18
+ module FileSupport
19
+ def self.included(base)
20
+ base.extend(ClassMethods)
21
+ end
22
+
23
+ # Required class methods to support file operations.
24
+ module ClassMethods
25
+ # The default name to use for the configuration file.
26
+ #
27
+ # @param filename [String] The name of the configuration file.
28
+ # @return [String] The name of the configuration file.
29
+ def config_file_name(filename = nil)
30
+ @config_file_name = filename unless filename.nil?
31
+ @config_file_name ||= 'config'
32
+ end
33
+
34
+ # The default path to use for the configuration file.
35
+ #
36
+ # @param path [String] The path to the configuration file.
37
+ # @return [String] The path to the configuration file.
38
+ def config_file_path(path = nil)
39
+ @config_file_path = path unless path.nil?
40
+ @config_file_path ||= '.'
41
+ end
42
+
43
+ # The file extensions supported by this configuration.
44
+ #
45
+ # @param format [Symbol] Optional format to get the extensions for. If
46
+ # specified, only returns the extensions for that format.
47
+ # @return [Array<String>]
48
+ def file_extensions(format: nil)
49
+ @config_file_formats ||= {}
50
+ if format
51
+ return @config_file_formats[format][:extensions] if @config_file_formats.key?(format)
52
+
53
+ raise FileFormatError, "File format not found: #{format}"
54
+ end
55
+
56
+ @config_file_formats.values.map { |o| o[:extensions] }.flatten
57
+ end
58
+
59
+ # Register support for a file format.
60
+ #
61
+ # @param format [Symbol] The format to register.
62
+ # @param opts [Hash] The options for the format.
63
+ # @option opts [Class] :class The class to use for the format. Defaults to
64
+ # ConfigSL::FileFormat::`format`, where `format` is capitalized.
65
+ # @option opts [Array<String>] :extensions File extensions for the format.
66
+ # defaults to those defined in `opts[:class]`.
67
+ def register_file_format(format, opts = {})
68
+ @config_file_formats ||= {}
69
+ opts[:class] ||= ConfigSL::FileFormat.const_get(format.capitalize)
70
+ opts[:extensions] ||= opts[:class].extensions
71
+
72
+ @config_file_formats[format] = opts
73
+ end
74
+
75
+ private
76
+
77
+ # Find the configuration file based on the default path, name, and defined
78
+ # formats.
79
+ #
80
+ # The returned files are ordered based on how their formats are defined.
81
+ # For example:
82
+ #
83
+ # register_file_format :yaml
84
+ # register_file_format :json
85
+ #
86
+ # would result in the YAML file being returned first if both are found.
87
+ #
88
+ # @param path [String] Optional path to look for the file. If provided,
89
+ # this method will raise an error the exact file is not found.
90
+ # @param format [Symbol] Optional format to look for the file in. If
91
+ # provided, will only match files of the given format. Ignored if `path`
92
+ # is provided.
93
+ # @return [Array<String>] Array of matching files.
94
+ def find_file(path: nil, format: nil)
95
+ paths = Dir.glob(
96
+ path.nil? ? "#{config_file_name}.{#{file_extensions(format:).join(',')}}" : path,
97
+ base: path.nil? ? config_file_path : nil
98
+ )
99
+
100
+ raise FileNotFoundError, 'No configuration file found!' if paths.empty?
101
+
102
+ paths.map { |p| File.join(config_file_path, p) }
103
+ end
104
+
105
+ # Find the format for a file given its extension.
106
+ #
107
+ # @param extension [String] The file extension to get the format for.
108
+ # @return [Symbol] The format for the file.
109
+ #
110
+ # @raise [FileFormatError] If no file formats have been defined.
111
+ # @raise [FileFormatError] If no file format is found for the extension.
112
+ def find_file_format(extension)
113
+ raise FileFormatError, 'No file formats have been defined' if @config_file_formats.nil?
114
+
115
+ extension = extension.sub(/^\./, '').to_sym
116
+ (@config_file_formats || {}).each do |format, opts|
117
+ return format if opts[:extensions].include?(extension)
118
+ end
119
+
120
+ raise FileFormatError, "No file format found for extension: #{extension}"
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'facets/boolean'
4
+
5
+ module ConfigSL
6
+ class FormatError < ArgumentError; end
7
+
8
+ # Format option values.
9
+ #
10
+ # This will format the values of the defined options when they are set on the
11
+ # config object. It will also format the values when they are retrieved, if
12
+ # they don't match their defined type.
13
+ #
14
+ # The default behavior is to cast the value as the defined type. If the value
15
+ # is nil, it will be returned as is.
16
+ #
17
+ # @todo Should we add an option to cast nil?
18
+ module Format
19
+ FORMATTERS = {
20
+ Array => :to_a,
21
+ FalseClass => :to_b,
22
+ Hash => :to_h,
23
+ Integer => :to_i,
24
+ String => ->(v) { v.to_s.encode('utf-8') },
25
+ Symbol => :to_sym,
26
+ TrueClass => :to_b
27
+ }.freeze
28
+
29
+ private
30
+
31
+ def get_value(name)
32
+ value = super
33
+ format_value(name, value)
34
+ end
35
+
36
+ def set_value(name, value)
37
+ raise InvalidOptionError, "Option #{name} is not defined" unless options.key?(name)
38
+
39
+ super(name, format_value(name, value))
40
+ end
41
+
42
+ def format_value(option, value)
43
+ return value if value.nil? || value.is_a?(options[option][:type])
44
+
45
+ apply_formatter(value, options[option][:type])
46
+ rescue StandardError => e
47
+ raise FormatError, "Value for #{option} is not compatible with " \
48
+ "#{options[option][:type]}: #{e.message}"
49
+ end
50
+
51
+ def apply_formatter(value, formatter)
52
+ if FORMATTERS.key?(formatter)
53
+ return value.send(FORMATTERS[formatter]) if FORMATTERS[formatter].is_a?(Symbol)
54
+ return FORMATTERS[formatter].call(value) if FORMATTERS[formatter].is_a?(Proc)
55
+ end
56
+
57
+ formatter.new(value)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigSL
4
+ # Load configuration from the environment.
5
+ #
6
+ # This module provides a way to load configuration values from environment
7
+ # variables. It checks for a variables using the name of the option, in upper
8
+ # snake case (e.g. `MY_OPTION`). You can add a prefix to all variable names
9
+ # using `from_environment_prefix`.
10
+ #
11
+ # from_environment_prefix 'DATABASE_'
12
+ # option :host, default: 'localhost'
13
+ #
14
+ # You can override the variable name for individual options by setting
15
+ # `env_variable`.
16
+ #
17
+ # option :host, default: 'localhost', env_variable: 'DB_HOST'
18
+ module FromEnvironment
19
+ def self.included(base)
20
+ base.extend ClassMethods
21
+ base.from_environment_prefix ''
22
+ end
23
+
24
+ # Class methods necessary for loading configuration from the environment.
25
+ module ClassMethods
26
+ # Set the prefix for environment variables.
27
+ #
28
+ # @param prefix [String] The prefix for the environment variables.
29
+ def from_environment_prefix(prefix)
30
+ @from_environment_prefix = prefix
31
+ end
32
+
33
+ # Create a new instance of the class using values from the environment.
34
+ #
35
+ # @return [self] The new config object
36
+ def from_environment
37
+ params = options.transform_values do |opts|
38
+ ENV.fetch(opts[:env_variable], opts[:default])
39
+ end
40
+
41
+ new(params)
42
+ end
43
+
44
+ # Ensure each option has an environment variable defined.
45
+ def option(name, opts = {})
46
+ opts[:env_variable] ||= "#{@from_environment_prefix}#{name.to_s.upcase}"
47
+ super
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'file_support'
4
+
5
+ module ConfigSL
6
+ # Load configuration from a file.
7
+ #
8
+ # This module provides a way to load configuration values from a file. It
9
+ # searches for files based on a default path, name, and one or more file
10
+ # formats.
11
+ #
12
+ # When multiple files are found, they will be sorted based on the order their
13
+ # formats are defined, and the first file will be loaded.
14
+ #
15
+ # For example:
16
+ #
17
+ # config_file_path 'config'
18
+ # config_file_name 'config'
19
+ #
20
+ # register_file_format :yaml
21
+ # register_file_format :json
22
+ #
23
+ # will search for files in the `config` directory, with the name `config`, and
24
+ # with the extensions `.yaml`, `.yml` and `.json`. If both `config.yaml` and
25
+ # `config.json` are found, `config.yaml` will be loaded.
26
+ #
27
+ # This module depends on the `FileSupport` module and will it include it your
28
+ # class if it has not been so already.
29
+ module FromFile
30
+ def self.included(base)
31
+ base.include(FileSupport) unless base.include?(FileSupport)
32
+ base.extend(ClassMethods)
33
+ end
34
+
35
+ # Required class methods for loading config files.
36
+ module ClassMethods
37
+ # Loads configuration from a file.
38
+ #
39
+ # If no path is specified, uses the file file that matches the default
40
+ # path, name, and file formats. If multiple files are found, they will be
41
+ # sorted based on the order the file formats are defined, adn the first
42
+ # file will be load.
43
+ #
44
+ # @param path [String] Optional path to the file to load.
45
+ # @param format [Symbol] Optional format to use for the file. Uses the
46
+ # file extension if not specified.
47
+ # @return [self]
48
+ def from_file(path = nil, format: nil)
49
+ path ||= find_file.first
50
+ format ||= find_file_format(File.extname(path))
51
+ file = @config_file_formats[format][:class].new(path)
52
+ new(file.read)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigSL
4
+ class ValidationError < RuntimeError; end
5
+
6
+ # Validates configuration options.
7
+ #
8
+ # This will check that all required options are set. Additionally, you can
9
+ # set `enum` to an array of valid values for an option.
10
+ #
11
+ # option :state, type: String, required: true, enum: %w[on off]
12
+ #
13
+ # @todo Implement custom validations.
14
+ module Validation
15
+ # Determine if the configuration is valid.
16
+ #
17
+ # @return [Boolean]
18
+ def valid?
19
+ options.keys.all? { |name| option_valid?(name) }
20
+ end
21
+
22
+ # Validate the configuration and raise an error if it is invalid.
23
+ #
24
+ # @raise [ValidationError] If the configuration is invalid.
25
+ def validate!
26
+ raise ValidationError, 'Invalid configuration' unless valid?
27
+ end
28
+
29
+ private
30
+
31
+ # Validates a single option.
32
+ #
33
+ # @param name [Symbol] The name of the option.
34
+ # @return [Boolean]
35
+ def option_valid?(name)
36
+ valid = !options[name][:required] || get_value(name)
37
+ valid &&= options[name][:enum].include?(get_value(name)) if options[name][:enum]
38
+
39
+ valid
40
+ end
41
+ end
42
+ end
data/lib/configsl.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'configsl/config'
4
+
5
+ module ConfigSL
6
+ VERSION = '1.0.0'
7
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: configsl
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - James I. Armes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-09-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: facets
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ description: A simple, modular, extensible DSL for configuration.
28
+ email: jamesiarmes@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files:
32
+ - README.md
33
+ - CHANGELOG.md
34
+ files:
35
+ - CHANGELOG.md
36
+ - Gemfile
37
+ - README.md
38
+ - lib/configsl.rb
39
+ - lib/configsl/config.rb
40
+ - lib/configsl/dsl.rb
41
+ - lib/configsl/exception.rb
42
+ - lib/configsl/file_format/base.rb
43
+ - lib/configsl/file_format/json.rb
44
+ - lib/configsl/file_format/yaml.rb
45
+ - lib/configsl/file_support.rb
46
+ - lib/configsl/format.rb
47
+ - lib/configsl/from_environment.rb
48
+ - lib/configsl/from_file.rb
49
+ - lib/configsl/validation.rb
50
+ homepage: https://github.com/jamesiarmes/configsl
51
+ licenses:
52
+ - MIT
53
+ metadata:
54
+ bug_tracker_uri: https://github.com/jamesiarmes/configsl/issues
55
+ changelog_uri: https://github.com/jamesiarmes/configsl/blob/main/CHANGELOG.md
56
+ homepage_uri: https://github.com/jamesiarmes/configsl
57
+ rubygems_mfa_required: 'true'
58
+ source_code_uri: https://github.com/jamesiarmes/configsl
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '3.2'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubygems_version: 3.5.9
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: A simple DSL for declarative configuration in ruby.
78
+ test_files: []