arkana 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/lib/arkana/config_parser.rb +2 -0
  3. data/lib/arkana/encoder.rb +0 -1
  4. data/lib/arkana/helpers/kotlin_template_helper.rb +22 -0
  5. data/lib/arkana/helpers/swift_template_helper.rb +7 -7
  6. data/lib/arkana/kotlin_code_generator.rb +56 -0
  7. data/lib/arkana/models/arguments.rb +12 -0
  8. data/lib/arkana/models/config.rb +21 -0
  9. data/lib/arkana/models/template_arguments.rb +4 -0
  10. data/lib/arkana/models/type.rb +10 -6
  11. data/lib/arkana/swift_code_generator.rb +8 -8
  12. data/lib/arkana/templates/kotlin/arkana.kt.erb +59 -0
  13. data/lib/arkana/templates/kotlin/arkana_protocol.kt.erb +13 -0
  14. data/lib/arkana/templates/kotlin/arkana_tests.kt.erb +137 -0
  15. data/lib/arkana/templates/kotlin/build.gradle.kts.erb +18 -0
  16. data/lib/arkana/templates/readme.erb +1 -1
  17. data/lib/arkana/templates/{arkana.swift.erb → swift/arkana.swift.erb} +6 -3
  18. data/lib/arkana/templates/{arkana_protocol.swift.erb → swift/arkana_protocol.swift.erb} +2 -2
  19. data/lib/arkana/templates/{arkana_tests.swift.erb → swift/arkana_tests.swift.erb} +40 -0
  20. data/lib/arkana/templates/{interfaces_readme.erb → swift/interfaces_readme.erb} +1 -1
  21. data/lib/arkana/version.rb +1 -1
  22. data/lib/arkana.rb +15 -6
  23. metadata +17 -12
  24. data/lib/arkana/helpers/enumerable.rb +0 -16
  25. /data/lib/arkana/templates/{arkana.podspec.erb → swift/arkana.podspec.erb} +0 -0
  26. /data/lib/arkana/templates/{interfaces.podspec.erb → swift/interfaces.podspec.erb} +0 -0
  27. /data/lib/arkana/templates/{interfaces_package.swift.erb → swift/interfaces_package.swift.erb} +0 -0
  28. /data/lib/arkana/templates/{package.swift.erb → swift/package.swift.erb} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb1bab49c8625e2a2bd1cb8bd378789df20767222714a950028af877a4cfeb81
4
- data.tar.gz: 9978033d03df9ea1c29528d8a506e6f82e43040c5675e81e5a84c2dc692a8b59
3
+ metadata.gz: 191140e1234c08e36b1d1bb3591bac7b77041edd8b7e00565f15480fd47bfe81
4
+ data.tar.gz: 8dd30c6bd576db0cd779b3f645cb9ec15541f5189dd71bd461c2f8895334a6e3
5
5
  SHA512:
6
- metadata.gz: 06d2d9248ba8d07e6faa667861a163599e246d61544168d7eebac39e974adf2af0ab4fdf28af7f3582727c4f304dd7d18f3692f7a5b521305865af4df7439e84
7
- data.tar.gz: 242062bff10a161e4a5734a828bcebed1694d3de700f2160720e17d87f3566c3ea68406e80f5e1c4c18a74294423df415881e0804ff75853f7ecf78eb410485a
6
+ metadata.gz: a79924122cac3f3a32e471f49218ff85227fab2898821e56436a32d6c8e7e6d8cea1af20538e71eb010383ac47cef7266964ccc1a9251ee058538227ae5a9a2d
7
+ data.tar.gz: dc8a20dfe2d1650cc14e1d3e8d24733229a795f8b6471272ff8d67cdaf72fd453925ea50d35d86386dfb1419c05fbf8910b8a7dbacbce4d80febed50883465cc
@@ -12,7 +12,9 @@ module ConfigParser
12
12
  def self.parse(arguments)
13
13
  yaml = YAML.load_file(arguments.config_filepath)
14
14
  config = Config.new(yaml)
15
+ config.include_environments(arguments.include_environments)
15
16
  config.current_flavor = arguments.flavor
17
+ config.current_lang = arguments.lang
16
18
  config.dotenv_filepath = arguments.dotenv_filepath
17
19
  UI.warn("Dotenv file was specified but couldn't be found at '#{config.dotenv_filepath}'") if config.dotenv_filepath && !File.exist?(config.dotenv_filepath)
18
20
  config
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "arkana/helpers/string"
4
- require "arkana/helpers/enumerable"
5
4
 
6
5
  # The encoder is responsible for finding the env vars for given keys, encoding them, and creating Secrets based on the generated data.
7
6
  module Encoder
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Utilities to reduce the amount of boilerplate code in `.kt.erb` template files.
4
+ module KotlinTemplateHelper
5
+ def self.kotlin_type(type)
6
+ case type
7
+ when :string then "String"
8
+ when :boolean then "Boolean"
9
+ when :integer then "Int"
10
+ else raise "Unknown variable type '#{type}' received."
11
+ end
12
+ end
13
+
14
+ def self.kotlin_decode_function(type)
15
+ case type
16
+ when :string then "decode"
17
+ when :boolean then "decodeBoolean"
18
+ when :integer then "decodeInt"
19
+ else raise "Unknown variable type '#{type}' received."
20
+ end
21
+ end
22
+ end
@@ -4,18 +4,18 @@
4
4
  module SwiftTemplateHelper
5
5
  def self.swift_type(type)
6
6
  case type
7
- when :string then "String"
8
- when :boolean then "Bool"
9
- when :integer then "Int"
10
- else raise "Unknown variable type '#{type}' received.'"
7
+ when :string then "String"
8
+ when :boolean then "Bool"
9
+ when :integer then "Int"
10
+ else raise "Unknown variable type '#{type}' received.'"
11
11
  end
12
12
  end
13
13
 
14
14
  def self.protocol_getter(declaration_strategy)
15
15
  case declaration_strategy
16
- when "lazy var" then "mutating get"
17
- when "var", "let" then "get"
18
- else raise "Unknown declaration strategy '#{declaration_strategy}' received.'"
16
+ when "lazy var" then "mutating get"
17
+ when "var", "let" then "get"
18
+ else raise "Unknown declaration strategy '#{declaration_strategy}' received.'"
19
19
  end
20
20
  end
21
21
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "erb"
4
+ require "fileutils"
5
+ require_relative "helpers/string"
6
+
7
+ # Responsible for generating Kotlin source and test files.
8
+ module KotlinCodeGenerator
9
+ # Generates Kotlin code and test files for the given template arguments.
10
+ def self.generate(template_arguments:, config:)
11
+ kotlin_module_dir = config.result_path
12
+ kotlin_sources_dir = File.join(kotlin_module_dir, "src", "main", config.kotlin_sources_path, config.kotlin_package_name.split("."))
13
+ kotlin_tests_dir = File.join(kotlin_module_dir, "src", "test", config.kotlin_sources_path, config.kotlin_package_name.split("."))
14
+
15
+ if config.should_generate_gradle_build_file
16
+ set_up_kotlin_module(kotlin_module_dir, template_arguments)
17
+ end
18
+
19
+ set_up_kotlin_interfaces(kotlin_sources_dir, template_arguments, config)
20
+ set_up_kotlin_classes(kotlin_sources_dir, kotlin_tests_dir, template_arguments, config)
21
+ end
22
+
23
+ def self.set_up_kotlin_module(path, template_arguments)
24
+ dirname = File.dirname(__FILE__)
25
+ sources_dir = path
26
+ readme_template = File.read("#{dirname}/templates/readme.erb")
27
+ source_template = File.read("#{dirname}/templates/kotlin/build.gradle.kts.erb")
28
+ FileUtils.mkdir_p(path)
29
+ render(readme_template, template_arguments, File.join(path, "README.md"))
30
+ render(source_template, template_arguments, File.join(sources_dir, "build.gradle.kts"))
31
+ end
32
+
33
+ def self.set_up_kotlin_interfaces(path, template_arguments, config)
34
+ dirname = File.dirname(__FILE__)
35
+ sources_dir = path
36
+ source_template = File.read("#{dirname}/templates/kotlin/arkana_protocol.kt.erb")
37
+ FileUtils.mkdir_p(path)
38
+ render(source_template, template_arguments, File.join(sources_dir, "#{config.namespace}Environment.kt"))
39
+ end
40
+
41
+ def self.set_up_kotlin_classes(sources_dir, tests_dir, template_arguments, config)
42
+ dirname = File.dirname(__FILE__)
43
+ source_template = File.read("#{dirname}/templates/kotlin/arkana.kt.erb")
44
+ tests_template = File.read("#{dirname}/templates/kotlin/arkana_tests.kt.erb")
45
+ FileUtils.mkdir_p(sources_dir)
46
+ FileUtils.mkdir_p(tests_dir) if config.should_generate_unit_tests
47
+ render(source_template, template_arguments, File.join(sources_dir, "#{config.namespace}.kt"))
48
+ render(tests_template, template_arguments, File.join(tests_dir, "#{config.namespace}Test.kt")) if config.should_generate_unit_tests
49
+ end
50
+
51
+ def self.render(template, template_arguments, destination_file)
52
+ renderer = ERB.new(template, trim_mode: ">") # Don't automatically add newlines at the end of each template tag
53
+ result = renderer.result(template_arguments.get_binding)
54
+ File.write(destination_file, result)
55
+ end
56
+ end
@@ -10,12 +10,18 @@ class Arguments
10
10
  attr_reader :dotenv_filepath
11
11
  # @returns [string]
12
12
  attr_reader :flavor
13
+ # @returns [Array<string>]
14
+ attr_reader :include_environments
15
+ # @returns [string]
16
+ attr_reader :lang
13
17
 
14
18
  def initialize
15
19
  # Default values
16
20
  @config_filepath = ".arkana.yml"
17
21
  @dotenv_filepath = ".env" if File.exist?(".env")
18
22
  @flavor = nil
23
+ @include_environments = nil
24
+ @lang = "swift"
19
25
 
20
26
  OptionParser.new do |opt|
21
27
  opt.on("-c", "--config-filepath /path/to/your/.arkana.yml", "Path to your config file. Defaults to '.arkana.yml'") do |o|
@@ -27,6 +33,12 @@ class Arguments
27
33
  opt.on("-f", "--flavor FrostedFlakes", "Flavors are useful, for instance, when generating secrets for white-label projects. See the README for more information") do |o|
28
34
  @flavor = o
29
35
  end
36
+ opt.on("-i", "--include-environments debug,release", "Optionally pass the environments that you want Arkana to generate secrets for. Useful if you only want to build a certain environment, e.g. just Debug in local machines, while only building Staging and Release in CI. Separate the keys using a comma, without spaces. When omitted, Arkana generate secrets for all environments.") do |o|
37
+ @include_environments = o.split(",")
38
+ end
39
+ opt.on("-l", "--lang kotlin", "Language to produce keys for, e.g. kotlin, swift. Defaults to 'swift'. See the README for more information") do |o|
40
+ @lang = o
41
+ end
30
42
  end.parse!
31
43
  end
32
44
  end
@@ -16,6 +16,10 @@ class Config
16
16
  attr_reader :pod_name
17
17
  # @returns [string]
18
18
  attr_reader :result_path
19
+ # @returns [string]
20
+ attr_reader :kotlin_package_name
21
+ # @returns [string]
22
+ attr_reader :kotlin_sources_path
19
23
  # @returns [string[]]
20
24
  attr_reader :flavors
21
25
  # @returns [string]
@@ -26,11 +30,17 @@ class Config
26
30
  attr_reader :package_manager
27
31
  # @returns [boolean]
28
32
  attr_reader :should_cocoapods_cross_import_modules
33
+ # @returns [boolean]
34
+ attr_reader :should_generate_gradle_build_file
35
+ # @returns [int]
36
+ attr_reader :kotlin_jvm_toolchain_version
29
37
 
30
38
  # @returns [string]
31
39
  attr_accessor :current_flavor
32
40
  # @returns [string]
33
41
  attr_accessor :dotenv_filepath
42
+ # @returns [string]
43
+ attr_accessor :current_lang
34
44
 
35
45
  # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
36
46
  def initialize(yaml)
@@ -42,6 +52,8 @@ class Config
42
52
  @import_name = yaml["import_name"] || default_name
43
53
  @pod_name = yaml["pod_name"] || default_name
44
54
  @result_path = yaml["result_path"] || default_name
55
+ @kotlin_package_name = yaml["kotlin_package_name"] || "com.arkanakeys"
56
+ @kotlin_sources_path = yaml["kotlin_sources_path"] || "kotlin"
45
57
  @flavors = yaml["flavors"] || []
46
58
  @swift_declaration_strategy = yaml["swift_declaration_strategy"] || "let"
47
59
  @should_generate_unit_tests = yaml["should_generate_unit_tests"]
@@ -49,6 +61,9 @@ class Config
49
61
  @package_manager = yaml["package_manager"] || "spm"
50
62
  @should_cocoapods_cross_import_modules = yaml["should_cocoapods_cross_import_modules"]
51
63
  @should_cocoapods_cross_import_modules = true if @should_cocoapods_cross_import_modules.nil?
64
+ @should_generate_gradle_build_file = yaml["should_generate_gradle_build_file"]
65
+ @should_generate_gradle_build_file = true if @should_generate_gradle_build_file.nil?
66
+ @kotlin_jvm_toolchain_version = yaml["kotlin_jvm_toolchain_version"] || 11
52
67
  end
53
68
  # rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
54
69
 
@@ -63,4 +78,10 @@ class Config
63
78
  def all_keys
64
79
  global_secrets + environment_keys
65
80
  end
81
+
82
+ def include_environments(environments)
83
+ return unless environments
84
+
85
+ @environments = @environments.select { |e| environments.map(&:downcase).include?(e.downcase) }
86
+ end
66
87
  end
@@ -20,6 +20,10 @@ class TemplateArguments
20
20
  @pod_name = config.pod_name
21
21
  # The top level namespace in which the keys will be generated. Often an enum.
22
22
  @namespace = config.namespace
23
+ # Name of the kotlin package to be used for the generated code.
24
+ @kotlin_package_name = config.kotlin_package_name
25
+ # The kotlin JVM toolchain JDK version to be used in the generated build.gradle file.
26
+ @kotlin_jvm_toolchain_version = config.kotlin_jvm_toolchain_version
23
27
  # The property declaration strategy declared in the config file.
24
28
  @swift_declaration_strategy = config.swift_declaration_strategy
25
29
  # Whether unit tests should be generated.
@@ -8,12 +8,16 @@ module Type
8
8
 
9
9
  def self.new(string_value:)
10
10
  case string_value
11
- when "true", "false"
12
- BOOLEAN
13
- when /^\d+$/
14
- INTEGER
15
- else
16
- STRING
11
+ when "true", "false"
12
+ BOOLEAN
13
+ when /^\d+$/
14
+ # Handles cases like "0001" which should be interpreted as strings
15
+ return STRING if string_value.to_i.to_s != string_value
16
+ # Handle int overflow
17
+ return STRING if string_value.to_i > (2**31) - 1
18
+ INTEGER
19
+ else
20
+ STRING
17
21
  end
18
22
  end
19
23
  end
@@ -17,11 +17,11 @@ module SwiftCodeGenerator
17
17
 
18
18
  def self.set_up_interfaces_swift_package(path, template_arguments, config)
19
19
  dirname = File.dirname(__FILE__)
20
- readme_template = File.read("#{dirname}/templates/interfaces_readme.erb")
21
- package_template = File.read("#{dirname}/templates/interfaces_package.swift.erb")
22
- podspec_template = File.read("#{dirname}/templates/interfaces.podspec.erb")
20
+ readme_template = File.read("#{dirname}/templates/swift/interfaces_readme.erb")
21
+ package_template = File.read("#{dirname}/templates/swift/interfaces_package.swift.erb")
22
+ podspec_template = File.read("#{dirname}/templates/swift/interfaces.podspec.erb")
23
23
  sources_dir = File.join(path, "Sources")
24
- source_template = File.read("#{dirname}/templates/arkana_protocol.swift.erb")
24
+ source_template = File.read("#{dirname}/templates/swift/arkana_protocol.swift.erb")
25
25
  FileUtils.mkdir_p(path)
26
26
  FileUtils.mkdir_p(sources_dir)
27
27
  render(podspec_template, template_arguments, File.join(path, "#{config.pod_name.capitalize_first_letter}Interfaces.podspec")) if config.package_manager == "cocoapods"
@@ -33,12 +33,12 @@ module SwiftCodeGenerator
33
33
  def self.set_up_swift_package(path, template_arguments, config)
34
34
  dirname = File.dirname(__FILE__)
35
35
  readme_template = File.read("#{dirname}/templates/readme.erb")
36
- package_template = File.read("#{dirname}/templates/package.swift.erb")
36
+ package_template = File.read("#{dirname}/templates/swift/package.swift.erb")
37
37
  sources_dir = File.join(path, "Sources")
38
- source_template = File.read("#{dirname}/templates/arkana.swift.erb")
38
+ source_template = File.read("#{dirname}/templates/swift/arkana.swift.erb")
39
39
  tests_dir = File.join(path, "Tests") if config.should_generate_unit_tests
40
- tests_template = File.read("#{dirname}/templates/arkana_tests.swift.erb")
41
- podspec_template = File.read("#{dirname}/templates/arkana.podspec.erb")
40
+ tests_template = File.read("#{dirname}/templates/swift/arkana_tests.swift.erb")
41
+ podspec_template = File.read("#{dirname}/templates/swift/arkana.podspec.erb")
42
42
  FileUtils.mkdir_p(path)
43
43
  FileUtils.mkdir_p(sources_dir)
44
44
  FileUtils.mkdir_p(tests_dir) if config.should_generate_unit_tests
@@ -0,0 +1,59 @@
1
+ <% require "arkana/helpers/string" %>
2
+ <% require "arkana/helpers/kotlin_template_helper" %>
3
+ <% # TODO: Sort these import statements alphabetically %>
4
+ // DO NOT MODIFY
5
+ // Automatically generated by Arkana (https://github.com/rogerluan/arkana)
6
+ package <%= @kotlin_package_name %>
7
+
8
+
9
+ object <%= @namespace %> {
10
+ private val salt = listOf(<%= @salt.formatted %>)
11
+
12
+ internal fun decode(encoded: List<Int>, cipher: List<Int>): String {
13
+ val decoded = encoded.mapIndexed { index, item ->
14
+ (item xor cipher[(index % cipher.size)]).toByte()
15
+ }.toByteArray()
16
+ return decoded.toString(Charsets.UTF_8)
17
+ }
18
+
19
+ internal fun decodeInt(encoded: List<Int>, cipher: List<Int>): Int {
20
+ return decode(encoded = encoded, cipher = cipher).toInt()
21
+ }
22
+
23
+ internal fun decodeBoolean(encoded: List<Int>, cipher: List<Int>): Boolean {
24
+ return decode(encoded = encoded, cipher = cipher).toBoolean()
25
+ }
26
+
27
+ object Global {
28
+ <% @global_secrets.each_with_index do |secret, index| %>
29
+ val <%= secret.key.camel_case %>: <%= KotlinTemplateHelper.kotlin_type(secret.type) %>
30
+
31
+ get() {
32
+ val encoded = listOf(<%= secret.encoded_value %>)
33
+ return <%= KotlinTemplateHelper.kotlin_decode_function(secret.type) %>(encoded = encoded, cipher = salt)
34
+ }
35
+ <% unless index == @global_secrets.length - 1 %>
36
+
37
+ <% end %>
38
+ <% end %>
39
+ }
40
+
41
+ <% @environments.each_with_index do |environment, env_index| %>
42
+ object <%= environment %> : <%= @namespace %>Environment {
43
+ <% environment_protocol_secrets(environment).each_with_index do |secret, secret_index| %>
44
+ override val <%= secret.protocol_key.camel_case %>: <%= KotlinTemplateHelper.kotlin_type(secret.type) %>
45
+
46
+ get() {
47
+ val encoded = listOf(<%= secret.encoded_value %>)
48
+ return <%= KotlinTemplateHelper.kotlin_decode_function(secret.type) %>(encoded = encoded, cipher = salt)
49
+ }
50
+ <% unless secret_index == environment_protocol_secrets(environment).length - 1 %>
51
+
52
+ <% end %>
53
+ <% end %>
54
+ }
55
+ <% unless env_index == @environments.length - 1 %>
56
+
57
+ <% end %>
58
+ <% end %>
59
+ }
@@ -0,0 +1,13 @@
1
+ <% require "arkana/helpers/string" %>
2
+ <% require "arkana/helpers/kotlin_template_helper" %>
3
+ // DO NOT MODIFY
4
+ // Automatically generated by Arkana (https://github.com/rogerluan/arkana)
5
+ package <%= @kotlin_package_name %>
6
+
7
+
8
+ interface <%= @namespace %>Environment {
9
+ <% for secret in @environment_secrets.uniq(&:protocol_key) %>
10
+ val <%= secret.protocol_key.camel_case %>: <%= KotlinTemplateHelper.kotlin_type(secret.type) %>
11
+
12
+ <% end %>
13
+ }
@@ -0,0 +1,137 @@
1
+ <% require "arkana/helpers/string" %>
2
+ <% require "arkana/helpers/kotlin_template_helper" %>
3
+ // DO NOT MODIFY
4
+ // Automatically generated by Arkana (https://github.com/rogerluan/arkana)
5
+ package <%= @kotlin_package_name %>
6
+
7
+
8
+ import kotlin.test.Test
9
+ import kotlin.test.assertEquals
10
+ import kotlin.test.assertFalse
11
+ import kotlin.test.assertNotEquals
12
+ import kotlin.test.assertTrue
13
+
14
+ internal class <%= @namespace %>Test {
15
+ private val salt = listOf(<%= @salt.formatted %>)
16
+ private val globalSecrets = <%= @namespace %>.Global
17
+
18
+ @Test
19
+ fun test_decodeRandomHexKey_shouldDecode() {
20
+ <% hex_key = SecureRandom.hex(64) %>
21
+ <% secret = generate_test_secret(key: hex_key) %>
22
+ val encoded = listOf(<%= secret.encoded_value %>)
23
+ assertEquals(<%= @namespace %>.decode(encoded = encoded, cipher = salt), "<%= hex_key %>")
24
+ }
25
+
26
+ @Test
27
+ fun test_decodeRandomBase64Key_shouldDecode() {
28
+ <% base64_key = SecureRandom.base64(64) %>
29
+ <% secret = generate_test_secret(key: base64_key) %>
30
+ val encoded = listOf(<%= secret.encoded_value %>)
31
+ assertEquals(<%= @namespace %>.decode(encoded = encoded, cipher = salt), "<%= base64_key %>")
32
+ }
33
+
34
+ @Test
35
+ fun test_decodeUUIDKey_shouldDecode() {
36
+ <% uuid_key = SecureRandom.uuid %>
37
+ <% secret = generate_test_secret(key: uuid_key) %>
38
+ val encoded = listOf(<%= secret.encoded_value %>)
39
+ assertEquals(<%= @namespace %>.decode(encoded = encoded, cipher = salt), "<%= uuid_key %>")
40
+ }
41
+
42
+ @Test
43
+ fun test_decodeTrueBoolValue_shouldDecode() {
44
+ <% bool_key = "true" %>
45
+ <% secret = generate_test_secret(key: bool_key) %>
46
+ val encoded = listOf(<%= secret.encoded_value %>)
47
+ assertTrue(<%= @namespace %>.decodeBoolean(encoded = encoded, cipher = salt))
48
+ }
49
+
50
+ @Test
51
+ fun test_decodeFalseBoolValue_shouldDecode() {
52
+ <% bool_key = "false" %>
53
+ <% secret = generate_test_secret(key: bool_key) %>
54
+ val encoded = listOf(<%= secret.encoded_value %>)
55
+ assertFalse(<%= @namespace %>.decodeBoolean(encoded = encoded, cipher = salt))
56
+ }
57
+
58
+ @Test
59
+ fun test_decodeIntValue_shouldDecode() {
60
+ <% int_key = "42" %>
61
+ <% secret = generate_test_secret(key: int_key) %>
62
+ val encoded = listOf(<%= secret.encoded_value %>)
63
+ assertEquals(<%= @namespace %>.decodeInt(encoded = encoded, cipher = salt), 42)
64
+ }
65
+
66
+ @Test
67
+ fun test_decodeIntValueWithLeadingZeroes_shouldDecodeAsString() {
68
+ <% int_with_leading_zeroes_key = "0001" %>
69
+ <% secret = generate_test_secret(key: int_with_leading_zeroes_key) %>
70
+ val encoded = listOf(<%= secret.encoded_value %>)
71
+ assertEquals(<%= @namespace %>.decode(encoded = encoded, cipher = salt), "0001")
72
+ }
73
+
74
+ @Test
75
+ fun test_decodeMassiveIntValue_shouldDecodeAsString() {
76
+ <% int_with_massive_number_key = "92233720368547758079223372036854775807" %>
77
+ <% secret = generate_test_secret(key: int_with_massive_number_key) %>
78
+ val encoded = listOf(<%= secret.encoded_value %>)
79
+ assertEquals(<%= @namespace %>.decode(encoded = encoded, cipher = salt), "92233720368547758079223372036854775807")
80
+ }
81
+
82
+ @Test
83
+ fun test_decodeNegativeIntValue_shouldDecodeAsString() {
84
+ <% negative_int_key = "-42" %>
85
+ <% secret = generate_test_secret(key: negative_int_key) %>
86
+ val encoded = listOf(<%= secret.encoded_value %>)
87
+ assertEquals(<%= @namespace %>.decode(encoded = encoded, cipher = salt), "-42")
88
+ }
89
+
90
+ @Test
91
+ fun test_decodeFloatingPointValue_shouldDecodeAsString() {
92
+ <% float_key = "3.14" %>
93
+ <% secret = generate_test_secret(key: float_key) %>
94
+ val encoded = listOf(<%= secret.encoded_value %>)
95
+ assertEquals(<%= @namespace %>.decode(encoded = encoded, cipher = salt), "3.14")
96
+ }
97
+
98
+ @Test
99
+ fun test_encodeAndDecodeValueWithDollarSign_shouldDecode() {
100
+ <% dollar_sign_key = "real_$lim_shady" %>
101
+ <% secret = generate_test_secret(key: dollar_sign_key) %>
102
+ val encoded = listOf(<%= secret.encoded_value %>)
103
+ assertEquals(<%= @namespace %>.decode(encoded = encoded, cipher = salt), "real_\$lim_shady")
104
+ }
105
+ <% if ENV["ARKANA_RUNNING_CI_INTEGRATION_TESTS"] %>
106
+
107
+ @Test
108
+ fun test_decodeEnvVarFromDotfile_withDollarSign__andEscaped_andNoQuotes_shouldDecode() {
109
+ assertEquals(globalSecrets.secretWithDollarSignEscapedAndAndNoQuotesKey, "real_\$lim_shady")
110
+ }
111
+
112
+ @Test
113
+ fun test_decodeEnvVarFromDotfile_withDollarSign__andEscaped_andDoubleQuotes_shouldDecode() {
114
+ assertEquals(globalSecrets.secretWithDollarSignEscapedAndDoubleQuoteKey, "real_\$lim_shady")
115
+ }
116
+
117
+ @Test
118
+ fun test_decodeEnvVarFromDotfile_withDollarSign__andNotEscaped_andSingleQuotes_shouldDecode() {
119
+ assertEquals(globalSecrets.secretWithDollarSignNotEscapedAndSingleQuoteKey, "real_\$lim_shady")
120
+ }
121
+
122
+ @Test
123
+ fun test_decodeEnvVarFromDotfile_withDollarSign__andNotEscaped_andDoubleQuotes_shouldDecodeWithUnexpectedValue() {
124
+ assertNotEquals(globalSecrets.secretWithDollarSignNotEscapedAndDoubleQuotesKey, "real_\$lim_shady")
125
+ }
126
+
127
+ @Test
128
+ fun test_decodeEnvVarFromDotfile_withDollarSign__andNotEscaped_andNoQuotes_shouldDecodeWithUnexpectedValue() {
129
+ assertNotEquals(globalSecrets.secretWithDollarSignNotEscapedAndNoQuotesKey, "real_\$lim_shady")
130
+ }
131
+
132
+ @Test
133
+ fun test_decodeEnvVarFromDotfile_withWeirdCharacters_shouldDecode() {
134
+ assertEquals(globalSecrets.secretWithWeirdCharactersKey, "` ~ ! @ # % ^ & * ( ) _ - + = { [ } } | : ; ' < , > . ? /")
135
+ }
136
+ <% end %>
137
+ }
@@ -0,0 +1,18 @@
1
+ // DO NOT MODIFY
2
+ // Automatically generated by Arkana (https://github.com/rogerluan/arkana)
3
+
4
+ plugins {
5
+ id("kotlin")
6
+ }
7
+
8
+ kotlin {
9
+ jvmToolchain(<%= @kotlin_jvm_toolchain_version %>)
10
+ }
11
+
12
+ tasks.test {
13
+ useJUnitPlatform()
14
+ }
15
+
16
+ dependencies {
17
+ testImplementation(kotlin("test"))
18
+ }
@@ -1,4 +1,4 @@
1
1
  # <%= @namespace %>
2
2
 
3
3
 
4
- This Package is autogenerated by [Arkana](https://github.com/rogerluan/arkana). Do not attempt to modify it manually, otherwise your changes will be overriden on the next code generation process. Please visit [Arkana](https://github.com/rogerluan/arkana) to read more.
4
+ This Package is autogenerated by [Arkana](https://github.com/rogerluan/arkana). Do not attempt to modify it manually, otherwise your changes will be overridden on the next code generation process. Please visit [Arkana](https://github.com/rogerluan/arkana) to read more.
@@ -1,5 +1,5 @@
1
- <% require 'arkana/helpers/string' %>
2
- <% require 'arkana/helpers/swift_template_helper' %>
1
+ <% require "arkana/helpers/string" %>
2
+ <% require "arkana/helpers/swift_template_helper" %>
3
3
  <% # TODO: Sort these import statements alphabetically %>
4
4
  // DO NOT MODIFY
5
5
  // Automatically generated by Arkana (https://github.com/rogerluan/arkana)
@@ -55,7 +55,7 @@ public extension <%= @namespace %> {
55
55
  }
56
56
  }
57
57
 
58
- <% for environment in @environments %>
58
+ <% @environments.each_with_index do |environment, env_index| %>
59
59
  public extension <%= @namespace %> {
60
60
  struct <%= environment %>: <%= @namespace %>EnvironmentProtocol {
61
61
  public init() {}
@@ -72,4 +72,7 @@ public extension <%= @namespace %> {
72
72
  <% end %>
73
73
  }
74
74
  }
75
+ <% unless env_index == @environments.length - 1 %>
76
+
77
+ <% end %>
75
78
  <% end %>
@@ -1,5 +1,5 @@
1
- <% require 'arkana/helpers/string' %>
2
- <% require 'arkana/helpers/swift_template_helper' %>
1
+ <% require "arkana/helpers/string" %>
2
+ <% require "arkana/helpers/swift_template_helper" %>
3
3
  // DO NOT MODIFY
4
4
  // Automatically generated by Arkana (https://github.com/rogerluan/arkana)
5
5
 
@@ -86,6 +86,46 @@ final class <%= @namespace %>Tests: XCTestCase {
86
86
  XCTAssertEqual(<%= @namespace %>.decode(encoded: encoded, cipher: salt), 42)
87
87
  }
88
88
 
89
+ func test_decodeIntValueWithLeadingZeroes_shouldDecodeAsString() {
90
+ <% int_with_leading_zeroes_key = "0001" %>
91
+ <% secret = generate_test_secret(key: int_with_leading_zeroes_key) %>
92
+ let encoded: [UInt8] = [
93
+ <%= secret.encoded_value %>
94
+
95
+ ]
96
+ XCTAssertEqual(<%= @namespace %>.decode(encoded: encoded, cipher: salt), "0001")
97
+ }
98
+
99
+ func test_decodeMassiveIntValue_shouldDecodeAsString() {
100
+ <% int_with_massive_number_key = "92233720368547758079223372036854775807" %>
101
+ <% secret = generate_test_secret(key: int_with_massive_number_key) %>
102
+ let encoded: [UInt8] = [
103
+ <%= secret.encoded_value %>
104
+
105
+ ]
106
+ XCTAssertEqual(<%= @namespace %>.decode(encoded: encoded, cipher: salt), "92233720368547758079223372036854775807")
107
+ }
108
+
109
+ func test_decodeNegativeIntValue_shouldDecodeAsString() {
110
+ <% negative_int_key = "-42" %>
111
+ <% secret = generate_test_secret(key: negative_int_key) %>
112
+ let encoded: [UInt8] = [
113
+ <%= secret.encoded_value %>
114
+
115
+ ]
116
+ XCTAssertEqual(<%= @namespace %>.decode(encoded: encoded, cipher: salt), "-42")
117
+ }
118
+
119
+ func test_decodeFloatingPointValue_shouldDecodeAsString() {
120
+ <% float_key = "3.14" %>
121
+ <% secret = generate_test_secret(key: float_key) %>
122
+ let encoded: [UInt8] = [
123
+ <%= secret.encoded_value %>
124
+
125
+ ]
126
+ XCTAssertEqual(<%= @namespace %>.decode(encoded: encoded, cipher: salt), "3.14")
127
+ }
128
+
89
129
  func test_encodeAndDecodeValueWithDollarSign_shouldDecode() {
90
130
  <% dollar_sign_key = "real_$lim_shady" %>
91
131
  <% secret = generate_test_secret(key: dollar_sign_key) %>
@@ -1,3 +1,3 @@
1
1
  # <%= @namespace %>Interfaces
2
2
 
3
- This Package was autogenerated by [Arkana](https://github.com/rogerluan/arkana). Do not attempt to modify it manually, otherwise your changes will be overriden in the next code generation process. Please visit [Arkana](https://github.com/rogerluan/arkana) to read more.
3
+ This Package was autogenerated by [Arkana](https://github.com/rogerluan/arkana). Do not attempt to modify it manually, otherwise your changes will be overridden in the next code generation process. Please visit [Arkana](https://github.com/rogerluan/arkana) to read more.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Arkana
4
- VERSION = "1.5.0"
4
+ VERSION = "2.0.0"
5
5
  end
data/lib/arkana.rb CHANGED
@@ -3,9 +3,11 @@
3
3
  require_relative "arkana/config_parser"
4
4
  require_relative "arkana/encoder"
5
5
  require_relative "arkana/helpers/dotenv_helper"
6
+ require_relative "arkana/helpers/ui"
6
7
  require_relative "arkana/models/template_arguments"
7
8
  require_relative "arkana/salt_generator"
8
9
  require_relative "arkana/swift_code_generator"
10
+ require_relative "arkana/kotlin_code_generator"
9
11
  require_relative "arkana/version"
10
12
 
11
13
  # Top-level namespace for Arkana's execution entry point. When ran from CLI, `Arkana.run` is what is invoked.
@@ -30,11 +32,11 @@ module Arkana
30
32
  )
31
33
  rescue StandardError => e
32
34
  # TODO: Improve this by creating an Env/Debug helper
33
- puts("Something went wrong when parsing and encoding your secrets.")
34
- puts("Current Flavor: #{config.current_flavor}")
35
- puts("Dotenv Filepath: #{config.dotenv_filepath}")
36
- puts("Config Filepath: #{arguments.config_filepath}")
37
- raise e
35
+ UI.warn("Something went wrong when parsing and encoding your secrets.")
36
+ UI.warn("Current Flavor: #{config.current_flavor}")
37
+ UI.warn("Dotenv Filepath: #{config.dotenv_filepath}")
38
+ UI.warn("Config Filepath: #{arguments.config_filepath}")
39
+ UI.crash(e.message)
38
40
  end
39
41
  template_arguments = TemplateArguments.new(
40
42
  environment_secrets: environment_secrets,
@@ -42,7 +44,14 @@ module Arkana
42
44
  config: config,
43
45
  salt: salt,
44
46
  )
45
- SwiftCodeGenerator.generate(
47
+
48
+ generator = case config.current_lang.downcase
49
+ when "swift" then SwiftCodeGenerator
50
+ when "kotlin" then KotlinCodeGenerator
51
+ else UI.crash("Unknown output lang selected: #{config.current_lang}")
52
+ end
53
+
54
+ generator.method(:generate).call(
46
55
  template_arguments: template_arguments,
47
56
  config: config,
48
57
  )
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arkana
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roger Oba
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-29 00:00:00.000000000 Z
11
+ date: 2023-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dotenv
@@ -67,10 +67,11 @@ files:
67
67
  - lib/arkana/config_parser.rb
68
68
  - lib/arkana/encoder.rb
69
69
  - lib/arkana/helpers/dotenv_helper.rb
70
- - lib/arkana/helpers/enumerable.rb
70
+ - lib/arkana/helpers/kotlin_template_helper.rb
71
71
  - lib/arkana/helpers/string.rb
72
72
  - lib/arkana/helpers/swift_template_helper.rb
73
73
  - lib/arkana/helpers/ui.rb
74
+ - lib/arkana/kotlin_code_generator.rb
74
75
  - lib/arkana/models/arguments.rb
75
76
  - lib/arkana/models/config.rb
76
77
  - lib/arkana/models/salt.rb
@@ -79,15 +80,19 @@ files:
79
80
  - lib/arkana/models/type.rb
80
81
  - lib/arkana/salt_generator.rb
81
82
  - lib/arkana/swift_code_generator.rb
82
- - lib/arkana/templates/arkana.podspec.erb
83
- - lib/arkana/templates/arkana.swift.erb
84
- - lib/arkana/templates/arkana_protocol.swift.erb
85
- - lib/arkana/templates/arkana_tests.swift.erb
86
- - lib/arkana/templates/interfaces.podspec.erb
87
- - lib/arkana/templates/interfaces_package.swift.erb
88
- - lib/arkana/templates/interfaces_readme.erb
89
- - lib/arkana/templates/package.swift.erb
83
+ - lib/arkana/templates/kotlin/arkana.kt.erb
84
+ - lib/arkana/templates/kotlin/arkana_protocol.kt.erb
85
+ - lib/arkana/templates/kotlin/arkana_tests.kt.erb
86
+ - lib/arkana/templates/kotlin/build.gradle.kts.erb
90
87
  - lib/arkana/templates/readme.erb
88
+ - lib/arkana/templates/swift/arkana.podspec.erb
89
+ - lib/arkana/templates/swift/arkana.swift.erb
90
+ - lib/arkana/templates/swift/arkana_protocol.swift.erb
91
+ - lib/arkana/templates/swift/arkana_tests.swift.erb
92
+ - lib/arkana/templates/swift/interfaces.podspec.erb
93
+ - lib/arkana/templates/swift/interfaces_package.swift.erb
94
+ - lib/arkana/templates/swift/interfaces_readme.erb
95
+ - lib/arkana/templates/swift/package.swift.erb
91
96
  - lib/arkana/version.rb
92
97
  homepage: https://github.com/rogerluan/arkana
93
98
  licenses:
@@ -112,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
117
  - !ruby/object:Gem::Version
113
118
  version: '0'
114
119
  requirements: []
115
- rubygems_version: 3.3.7
120
+ rubygems_version: 3.4.10
116
121
  signing_key:
117
122
  specification_version: 4
118
123
  summary: Store your keys and secrets away from your source code. Designed for Android
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Enumerable extensions and utilities.
4
- module Enumerable
5
- # NOTE: This is a backport of Ruby 2.7 filter_map. This method can be deleted when the minimum target Ruby version is 2.7
6
- # We're not gating against redefining the method (e.g. via `unless Enumerable.method_defined? :filter_map`) because this
7
- # would reduce the code coverage when analysing code coverage on Ruby versions >= 2.7
8
- def filter_map
9
- return to_enum(:filter_map) unless block_given?
10
-
11
- each_with_object([]) do |item, res|
12
- processed = yield(item)
13
- res << processed if processed
14
- end
15
- end
16
- end