secure-keys 1.1.2 → 1.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8cd5c377f201fdb4fd22802645629371e0846768d444398b5fc8de07152edb58
4
- data.tar.gz: 845e7fb862ec80987753479bfba9b978336c3090123c41b7dac765ec20a1465b
3
+ metadata.gz: cdab80c05ee6ac029d64ec53aef700bc77e9126398f886f6fc7e0ae529297535
4
+ data.tar.gz: 38176c478f562dfcacd51e62b051f49705cec3cc66a586e20487038965a9976e
5
5
  SHA512:
6
- metadata.gz: 301b39d752b908b2f8817223a74ee84d8f08a9e3da3f7c41be022d03f392af2a0cb0dd2a320ed73e0c643536826606dad87a9c384da4c3c58c2e2e1af8149c6c
7
- data.tar.gz: bd83843339d9169c06e80e31ed3b0fb98f574cd2367001158e668ae38534cc287f8f959b57fbadf343da89e9ddd216f89952c2289a489a9843dbd6ab2bff80ba
6
+ metadata.gz: 77e197f322a085f56ce57eef897fdcc156c2c5fe3be9decd1464b396080cfbab2acb39def1787c872b7980c8fb6b9530b6487ccbd2b8b87e93beff57a64f1d51
7
+ data.tar.gz: ffc4ba7aedeff64d0d30f214564b2ec48f4658d4a5eef8e428877b7d98ab896d5a108e0a9e50bdd9668cfa62496d0b9929b6efab50f42814ff4ae1871dc22b14
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <div style="display: flex; gap: 10px; padding-bottom: 20px;">
2
- <img src="https://img.shields.io/badge/version-1.0.0-cyan" alt="Keys Version 1.0.0">
2
+ <img src="https://img.shields.io/badge/version-1.1.4-cyan" alt="SecureKeys version">
3
3
 
4
4
  <img src="https://img.shields.io/badge/iOS-^13.0-blue" alt="iOS version 13.0">
5
5
 
@@ -138,8 +138,11 @@ secure-keys --help
138
138
  Usage: secure-keys [--options]
139
139
 
140
140
  -h, --help Use the provided commands to select the params
141
+ --xcframework Add the xcframework to the target
141
142
  -d, --delimiter DELIMITER The delimiter to use for the key access (default: ",")
143
+ --[no-]generate Generate the SecureKeys.xcframework
142
144
  -i, --identifier IDENTIFIER The identifier to use for the key access (default: "secure-keys")
145
+ --verbose Enable verbose mode (default: false)
143
146
  -v, --version Show the secure-keys version
144
147
  ```
145
148
 
@@ -165,16 +168,16 @@ import SecureKeys
165
168
  // Using key directly in the code
166
169
  let apiKey = SecureKey.apiKey.decryptedValue
167
170
 
168
- // Using key from `Key` enum
171
+ // Using key from `SecureKey` enum
169
172
  let someKey: String = key(for: .someKey)
170
173
 
171
- // Alternative way to use key from `Key` enum
174
+ // Alternative way to use key from `SecureKey` enum
172
175
  let someKey: String = key(.someKey)
173
176
 
174
- // Using raw value from `Key` enum
177
+ // Using raw value from `SecureKey` enum
175
178
  let apiKey: SecureKey = "apiKey".secretKey
176
179
 
177
- // Using raw value from `Key` enum with decrypted value
180
+ // Using raw value from `SecureKey` enum with decrypted value
178
181
  let apiKey: String = "apiKey".secretKey.decryptedValue
179
182
 
180
183
  // Using `key` method to get the key
@@ -183,6 +186,73 @@ let apiKey: String = .key(for: .apiKey)
183
186
 
184
187
  ## How to install the `SecureKeys.xcframework` in the iOS project
185
188
 
189
+ ### Automatically
190
+
191
+ > [!IMPORTANT]
192
+ > You can see more information about the command using the `--help` option.
193
+
194
+ ```bash
195
+ secure-keys --xcframework --help
196
+
197
+ # Output
198
+ Usage: secure-keys --xcframework [--options]
199
+
200
+ -h, --help Use the provided commands to select the params
201
+ --[no-]add Add the SecureKeys XCFramework to the Xcode project (default: true)
202
+ -t, --target TARGET The target to add the xcframework
203
+ -r, --replace Replace the existing xcframework in the Xcode project (default: false)
204
+ -x, --xcodeproj XCODEPROJ The Xcode project path (default: the first found Xcode project)
205
+ ```
206
+
207
+ From the `secure-keys` command, you can use the `--xcframework` option to add the `SecureKeys.xcframework` to the iOS project.
208
+
209
+ ```bash
210
+ secure-keys --xcframework --target "YourTargetName" --add
211
+ ```
212
+
213
+ If you want to add the `SecureKeys.xcframework` to an iOS that already contains the `SecureKeys` source code, you can use the `--replace` option.
214
+
215
+ ```bash
216
+ secure-keys --xcframework --target "YourTargetName" --replace
217
+ ```
218
+
219
+ > [!IMPORTANT]
220
+ > If you don't need to generate the `SecureKeys.xcframework` every time, you can use the `--no-generate` option.
221
+
222
+ ```bash
223
+ secure-keys --no-generate --xcframework --target "YourTargetName"
224
+ ```
225
+
226
+ Also, you can specify your Xcode project path using the `--xcodeproj` option.
227
+
228
+ ```bash
229
+ secure-keys --xcframework --target "YourTargetName" --xcodeproj "/path/to/your/project.xcodeproj"
230
+ ```
231
+
232
+ > [!IMPORTANT]
233
+ > By default, the xcodeproj path would be the first found Xcode project.
234
+
235
+ If you don't want to use the CLI options, you can configure some env variable to interact with the `secure-keys` command.
236
+
237
+ ```bash
238
+ # e.g (Large version)
239
+ export SECURE_KEYS_XCFRAMEWORK_TARGET="YourTargetName"
240
+ export SECURE_KEYS_XCFRAMEWORK_ADD=true
241
+ export SECURE_KEYS_XCFRAMEWORK_REPLACE=true
242
+ export SECURE_KEYS_XCFRAMEWORK_XCODEPROJ="/path/to/your/project.xcodeproj"
243
+
244
+ # e.g (Short version)
245
+ export XCFRAMEWORK_TARGET="YourTargetName"
246
+ export XCFRAMEWORK_ADD=true
247
+ export XCFRAMEWORK_REPLACE=true
248
+ export XCFRAMEWORK_XCODEPROJ="/path/to/your/project.xcodeproj"
249
+
250
+ # Run the command
251
+ secure-keys --xcframework
252
+ ```
253
+
254
+ ### Manually
255
+
186
256
  1. From the iOS project, click on the project target, select the `General` tab, and scroll down to the `Frameworks, Libraries, and Embedded Content` section.
187
257
 
188
258
  ![Project Target](/docs/assets/add-xcframework-to-ios-project/first-step.png)
data/bin/secure-keys CHANGED
@@ -5,4 +5,4 @@ require 'dotenv/load'
5
5
  require_relative '../lib/keys'
6
6
 
7
7
  # Generate the keys
8
- SecureKeys::Generator.new.setup
8
+ SecureKeys.run
@@ -10,18 +10,37 @@ module SecureKeys
10
10
  # Configure the default arguments
11
11
  @arguments = {
12
12
  delimiter: nil,
13
+ generate: true,
13
14
  identifier: nil,
15
+ verbose: false,
14
16
  }
15
17
 
16
18
  # Fetch the argument value by key
17
19
  # from CLI arguments or environment variables
18
20
  #
19
- # @param key [Symbol] the argument key
21
+ # @param key [Array|Symbol] the argument key
20
22
  # @param default [String] the default value
21
23
  #
22
24
  # @return [String] the argument value
23
25
  def self.fetch(key:, default: nil)
24
- @arguments[key.to_sym] || ENV.fetch("secure_keys_#{key}".upcase, nil) || default
26
+ keys = Array(key).map(&:to_sym)
27
+ joined_keys = keys.join('_').upcase
28
+ @arguments.dig(*keys) || ENV["SECURE_KEYS_#{joined_keys}"] || ENV[joined_keys] || default
29
+ end
30
+
31
+ # Set the value of the key
32
+ # @param key [Symbol] the key to be updated
33
+ # @param value [String] the value to be updated
34
+ def self.set(key:, value:)
35
+ @arguments[key.to_sym] = value
36
+ end
37
+
38
+ # Append the argument value by key
39
+ # @param key [Symbol] the argument key
40
+ # @param value [String] the argument value
41
+ def self.deep_merge(key:, value:)
42
+ @arguments[key.to_sym] ||= {} # Initialize the key if it doesn't exist
43
+ @arguments[key.to_sym].merge!(value)
25
44
  end
26
45
  end
27
46
  end
@@ -3,6 +3,7 @@
3
3
  require 'optparse'
4
4
  require_relative '../../globals/globals'
5
5
  require_relative './handler'
6
+ require_relative './xcframework/parser'
6
7
 
7
8
  module SecureKeys
8
9
  module Core
@@ -16,7 +17,8 @@ module SecureKeys
16
17
 
17
18
  # Configure the arguement parser
18
19
  configure!
19
- parse!(into: Handler.arguments)
20
+ order!(into: Handler.arguments)
21
+ configure_sub_arguments
20
22
  end
21
23
 
22
24
  private
@@ -28,14 +30,25 @@ module SecureKeys
28
30
  exit(0)
29
31
  end
30
32
 
33
+ on('--xcframework', 'Add the xcframework to the target') do
34
+ XCFramework::Parser.new
35
+ end
36
+
31
37
  on('-d', '--delimiter DELIMITER', String, "The delimiter to use for the key access (default: \"#{Globals.default_key_delimiter}\")")
38
+ on('--[no-]generate', TrueClass, 'Generate the SecureKeys.xcframework')
32
39
  on('-i', '--identifier IDENTIFIER', String, "The identifier to use for the key access (default: \"#{Globals.default_key_access_identifier}\")")
40
+ on('--verbose', TrueClass, 'Enable verbose mode (default: false)')
33
41
 
34
42
  on('-v', '--version', 'Show the secure-keys version') do
35
43
  puts "secure-keys version: v#{SecureKeys::VERSION}"
36
44
  exit(0)
37
45
  end
38
46
  end
47
+
48
+ # Configure the sub arguments
49
+ def configure_sub_arguments
50
+ Handler.set(key: :xcframework, value: XCFramework::Handler.arguments)
51
+ end
39
52
  end
40
53
  end
41
54
  end
@@ -0,0 +1,23 @@
1
+ module SecureKeys
2
+ module Core
3
+ module Console
4
+ module Argument
5
+ module XCFramework
6
+ class Handler
7
+ class << self
8
+ attr_reader :arguments
9
+ end
10
+
11
+ # Configure the default arguments
12
+ @arguments = {
13
+ add: true,
14
+ replace: false,
15
+ target: nil,
16
+ xcodeproj: nil,
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require_relative '../../../globals/globals'
5
+ require_relative './handler'
6
+
7
+ module SecureKeys
8
+ module Core
9
+ module Console
10
+ module Argument
11
+ module XCFramework
12
+ class Parser < OptionParser
13
+ # Initialize the argument parser with the default options
14
+ def initialize
15
+ super('Usage: secure-keys --xcframework [--options]')
16
+ separator('')
17
+
18
+ # Configure the arguement parser
19
+ configure!
20
+ order!(into: Handler.arguments)
21
+ end
22
+
23
+ private
24
+
25
+ # Configure the argument parser
26
+ def configure!
27
+ on('-h', '--help', 'Use the provided commands to select the params') do
28
+ puts self
29
+ exit(0)
30
+ end
31
+
32
+ on('--[no-]add', TrueClass, 'Add the SecureKeys XCFramework to the Xcode project (default: true)')
33
+ on('-t', '--target TARGET', String, 'The target to add the xcframework')
34
+ on('-r', '--replace', TrueClass, 'Replace the existing xcframework in the Xcode project (default: false)')
35
+ on('-x', '--xcodeproj XCODEPROJ', String, 'The Xcode project path (default: the first found Xcode project)')
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,123 @@
1
+ require 'colorize'
2
+ require 'logger'
3
+ require 'tty-screen'
4
+ require_relative '../globals/globals'
5
+
6
+ module SecureKeys
7
+ module Core
8
+ module Console
9
+ module Logger
10
+ module_function
11
+
12
+ # Log a success message
13
+ # @param message [String] the message to log
14
+ def success(message:)
15
+ logger.info(message.to_s.green)
16
+ end
17
+
18
+ # Log an error message
19
+ # @param message [String] the message to log
20
+ def error(message:)
21
+ logger.warn(message.to_s.red)
22
+ end
23
+
24
+ # Log an important message
25
+ # @param message [String] the message to log
26
+ def important(message:)
27
+ logger.info(message.to_s.blue)
28
+ end
29
+
30
+ # Log a warning message
31
+ # @param message [String] the message to log
32
+ def warning(message:)
33
+ logger.info(message.to_s.yellow)
34
+ end
35
+
36
+ # Log a message without any formatting
37
+ # @param message [String] the message to log
38
+ def message(message:)
39
+ logger.info(message.to_s)
40
+ end
41
+
42
+ # Log a deprecated message
43
+ # @param message [String] the message to log
44
+ def deprecated(message:)
45
+ logger.error(message.to_s.deprecated)
46
+ end
47
+
48
+ # Log a command message
49
+ # @param command [String] the command to log
50
+ def command(command:)
51
+ logger.info("$ #{command}".cyan)
52
+ end
53
+
54
+ # Log a verbose message
55
+ # @param message [String] the message to log
56
+ def verbose(message:)
57
+ logger.debug(message.to_s) if Globals.verbose?
58
+ end
59
+
60
+ # Crash the terminal with a message
61
+ # @param message [String] the message to log
62
+ def crash!(message:)
63
+ raise(StandardError.new, message)
64
+ end
65
+
66
+ # Kill the terminal with a message
67
+ # @param message [String] the message to log
68
+ def kill!(message:)
69
+ error(message:)
70
+ exit(1)
71
+ end
72
+
73
+ # Log a command output
74
+ # @param command [String] the command to log
75
+ def command_output(command:)
76
+ actual = encode_as_utf_8_if_possible(message: command).split("\r")
77
+ .last || ''
78
+ actual.split("\n").each do |cmd|
79
+ prefix = cmd.include?('▸') ? '' : '▸ '
80
+ logger.info("#{prefix} #{cmd.magenta}")
81
+ end
82
+ end
83
+
84
+ # Create a logger instance if needed
85
+ # @return [Logger] the logger instance
86
+ def logger
87
+ return @log unless @log.nil?
88
+
89
+ $stdout.sync = true
90
+ @log ||= ::Logger.new($stdout)
91
+ @log.formatter = proc do |severity, datetime, _, message|
92
+ "#{format_string(datetime:, severity:)} #{message}\n"
93
+ end
94
+
95
+ @log
96
+ end
97
+
98
+ # Format the log string
99
+ # @param datetime [Time] the datetime to format
100
+ # @param severity [String] the severity of the log
101
+ # @return [String] the formatted string
102
+ def format_string(datetime: Time.now, severity: '')
103
+ return "#{severity} [#{datetime.strftime('%Y-%m-%d %H:%M:%S.%2N')}]: " if Globals.verbose?
104
+
105
+ "[#{datetime.strftime('%H:%M:%S')}]: "
106
+ end
107
+
108
+ # Encode a message as UTF-8 if possible
109
+ # @param message [String] the message to encode
110
+ # @return [String] the encoded message
111
+ def encode_as_utf_8_if_possible(message:)
112
+ return message if message.valid_encoding?
113
+
114
+ return message.encode(Encoding::UTF_8, Encoding::UTF_16) if message.dup
115
+ .force_encoding(Encoding::UTF_16)
116
+ .valid_encoding?
117
+
118
+ message.encode(Encoding::UTF_8, invalid: :replace)
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'open3'
4
+ require_relative './logger'
5
+ require_relative '../globals/globals'
6
+
7
+ module SecureKeys
8
+ module Core
9
+ module Console
10
+ module Shell
11
+ module_function
12
+
13
+ # Source: https://github.com/fastlane/fastlane/blob/5b2106db41be2ca272dfe5b99360f29879c707bb/fastlane/lib/fastlane/helper/sh_helper.rb#L28
14
+ # Executes a shell command
15
+ # All commands will be executed in the given block
16
+ # @param command [String] The command that should be executed
17
+ # @param error_handler [Block] A block that will be called with the output of the command if the command exists with a non-zero exit status
18
+ # @return [Array] An array containing the output of the command, the exit status and the command
19
+ def sh(command:, error_handler: nil)
20
+ previous_encoding = [Encoding.default_external, Encoding.default_internal]
21
+ Encoding.default_external = Encoding::UTF_8
22
+ Encoding.default_internal = Encoding::UTF_8
23
+ Logger.command(command:)
24
+
25
+ output = ''
26
+ exit_status = nil
27
+ Open3.popen2e(command) do |_stdin, io, thread|
28
+ io.sync = true
29
+ io.each do |line|
30
+ Logger.command_output(command: line.strip)
31
+ output << line
32
+ end
33
+ exit_status = thread.value
34
+ end
35
+
36
+ if exit_status.exitstatus.zero?
37
+ output << command
38
+ else
39
+ message = "Exit status of command '#{command}' was #{exit_status.exitstatus} instead of 0.\n#{output}"
40
+
41
+ if error_handler || block_given?
42
+ Logger.error(message:)
43
+ error_handler&.call(output)
44
+ else
45
+ Logger.crash!(message:)
46
+ end
47
+ end
48
+
49
+ return yield(exit_status || $CHILD_STATUS, output, command) if block_given?
50
+
51
+ [output, exit_status || $CHILD_STATUS, command]
52
+ rescue StandardError => e
53
+ raise e
54
+ ensure
55
+ Encoding.default_external = previous_encoding.first
56
+ Encoding.default_internal = previous_encoding.last
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -8,19 +8,10 @@ module SecureKeys
8
8
  # @param key [String] the key of the environment variable to fetch
9
9
  # @return [String] the value of the environment variable
10
10
  def fetch(key:)
11
- ENV[formatted_key(key:)]
11
+ ENV[key]
12
12
  rescue StandardError
13
13
  puts "❌ Error fetching the key: #{key} from ENV variables"
14
14
  end
15
-
16
- private
17
-
18
- # Formats the key to match the format of the environment variables.
19
- # @param key [String] the key to format
20
- # @return [String] the formatted key
21
- def formatted_key(key:)
22
- key.gsub('-', '_').uppercase
23
- end
24
15
  end
25
16
  end
26
17
  end
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative './globals/globals'
4
+ require_relative './environment/ci'
5
+ require_relative './environment/keychain'
6
+ require_relative './utils/swift/writer'
7
+ require_relative './utils/swift/package'
8
+ require_relative './utils/swift/swift'
9
+ require_relative './utils/swift/xcframework'
10
+ require_relative './utils/openssl/cipher'
11
+
12
+ module SecureKeys
13
+ module Core
14
+ class Generator
15
+ private
16
+
17
+ attr_accessor :cipher, :secrets_source, :secret_keys, :mapped_keys, :xcframework
18
+
19
+ public
20
+
21
+ def initialize
22
+ # Configure cipher
23
+ self.cipher = OpenSSL::Cipher.new
24
+ self.secrets_source = Globals.secret_keys_source
25
+
26
+ # Define the keys that we want to map
27
+ self.secret_keys = secrets_source.fetch(key: Globals.key_access_identifier)
28
+ .to_s
29
+ .split(Globals.key_delimiter)
30
+ .map(&:strip)
31
+
32
+ # Add the keys that we want to map
33
+ self.mapped_keys = secret_keys.map do |key|
34
+ encrypted_data = cipher.encrypt(value: secrets_source.fetch(key:))
35
+ { name: key.camelize, **encrypted_data }
36
+ end
37
+
38
+ # Configure the XCFramework
39
+ self.xcframework = Swift::XCFramework.new
40
+ end
41
+
42
+ def generate
43
+ if Globals.generate_xcframework?
44
+ pre_actions
45
+ generate_swift_package
46
+ write_keys
47
+ xcframework.generate
48
+ end
49
+
50
+ xcframework.configure_xcframework_to_xcodeproj
51
+ post_actions if Globals.generate_xcframework?
52
+ end
53
+
54
+ private
55
+
56
+ def generate_swift_package
57
+ package = Swift::Package.new
58
+ package.generate
59
+ end
60
+
61
+ def write_keys
62
+ writer = Swift::Writer.new(mapped_keys:,
63
+ secure_key_bytes: cipher.secure_key_bytes)
64
+ writer.write
65
+ end
66
+
67
+ def pre_actions
68
+ # Remove the keys directory
69
+ system("rm -rf #{Swift::KEYS_DIRECTORY}")
70
+ end
71
+
72
+ def post_actions
73
+ # Remove the keys directory
74
+ system("rm -rf #{Swift::SWIFT_PACKAGE_DIRECTORY}")
75
+
76
+ # Remove the build directory
77
+ system("rm -rf #{Swift::KEYS_DIRECTORY}/#{Swift::BUILD_DIRECTORY}")
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require_relative '../console/arguments/handler'
4
+ require_relative '../utils/swift/swift'
4
5
 
5
6
  module SecureKeys
6
7
  module Globals
@@ -14,7 +15,7 @@ module SecureKeys
14
15
 
15
16
  # Check for Jenkins, Travis CI, ... environment variables
16
17
  %w[JENKINS_HOME JENKINS_URL TRAVIS CI APPCENTER_BUILD_ID TEAMCITY_VERSION GO_PIPELINE_NAME bamboo_buildKey GITLAB_CI XCS TF_BUILD GITHUB_ACTION GITHUB_ACTIONS BITRISE_IO BUDDY CODEBUILD_BUILD_ARN].any? do |current|
17
- ENV[current].to_s.eql?('true')
18
+ ENV[current].to_s.to_boolean
18
19
  end
19
20
  end
20
21
 
@@ -24,6 +25,59 @@ module SecureKeys
24
25
  ENV.key?('CIRCLECI')
25
26
  end
26
27
 
28
+ # Check if the current instance is verbose
29
+ # @return [Bool] true if the current instance is verbose
30
+ def verbose?
31
+ Core::Console::Argument::Handler.fetch(key: :verbose)
32
+ .to_s
33
+ .to_boolean
34
+ end
35
+
36
+ # Check if the SecureKeys XCFramework should be generated
37
+ # @return [Bool] true if the SecureKeys XCFramework should be generated
38
+ def generate_xcframework?
39
+ Core::Console::Argument::Handler.fetch(key: :generate)
40
+ .to_s
41
+ .to_boolean
42
+ end
43
+
44
+ # Check if the SecureKeys XCFramework should be replaced
45
+ # @return [Bool] true if the SecureKeys XCFramework should be replaced
46
+ def replace_xcframework?
47
+ Core::Console::Argument::Handler.fetch(key: %i[xcframework replace])
48
+ .to_s
49
+ .to_boolean
50
+ end
51
+
52
+ # Check if the SecureKeys XCFramework should be added
53
+ # @return [Bool] true if the SecureKeys XCFramework should be added
54
+ def add_xcframework?
55
+ Core::Console::Argument::Handler.fetch(key: %i[xcframework add])
56
+ .to_s
57
+ .to_boolean
58
+ end
59
+
60
+ # Returns the Xcode project path
61
+ # @return [String] Xcode project path
62
+ def xcodeproj_path
63
+ Core::Console::Argument::Handler.fetch(key: %i[xcframework xcodeproj],
64
+ default: Dir.glob('**/*.xcodeproj').first)
65
+ end
66
+
67
+ # Returns the secure keys XCFramework path
68
+ # @return [String] secure keys XCFramework path
69
+ def secure_keys_xcframework_path
70
+ Dir.glob("**/#{Swift::KEYS_DIRECTORY}/#{Swift::XCFRAMEWORK_DIRECTORY}").first
71
+ end
72
+
73
+ # Determine the secret keys source based on the environment
74
+ # @return [Object] secret keys source
75
+ def secret_keys_source
76
+ return SecureKeys::Core::Environment::CI.new if ci?
77
+
78
+ SecureKeys::Core::Environment::Keychain.new
79
+ end
80
+
27
81
  # Returns the supported iOS platforms
28
82
  # @return [Array] supported iOS platforms
29
83
  def ios_platforms
@@ -0,0 +1,13 @@
1
+ require_relative './string/to_bool'
2
+ require_relative './string/camelize'
3
+
4
+ module Kernel
5
+ include BooleanCasting
6
+ include Camelize
7
+
8
+ String.include(BooleanCasting)
9
+ String.singleton_class.include(BooleanCasting)
10
+
11
+ String.include(Camelize)
12
+ String.singleton_class.include(Camelize)
13
+ end
@@ -0,0 +1,11 @@
1
+ # Adds some useful methods to the String class
2
+ module Camelize
3
+ # Convert a string to camel case format
4
+ # @return [String] the camel case formatted string
5
+ def camelize
6
+ words = split(/(?<=[a-z])(?=[A-Z])|[-_\s]+/) # Split at lowercase-to-uppercase transitions or explicit separators
7
+ .map(&:downcase) # Convert everything to lowercase for consistency
8
+
9
+ words.map.with_index { |word, index| index.zero? ? word : word.capitalize }.join
10
+ end
11
+ end