arkana 1.6.0 → 2.1.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 -1
  3. data/lib/arkana/encoder.rb +1 -2
  4. data/lib/arkana/helpers/kotlin_template_helper.rb +22 -0
  5. data/lib/arkana/kotlin_code_generator.rb +61 -0
  6. data/lib/arkana/models/arguments.rb +7 -1
  7. data/lib/arkana/models/config.rb +19 -0
  8. data/lib/arkana/models/template_arguments.rb +5 -1
  9. data/lib/arkana/salt_generator.rb +1 -1
  10. data/lib/arkana/swift_code_generator.rb +10 -10
  11. data/lib/arkana/templates/kotlin/arkana.kt.erb +59 -0
  12. data/lib/arkana/templates/kotlin/arkana_protocol.kt.erb +13 -0
  13. data/lib/arkana/templates/kotlin/arkana_tests.kt.erb +137 -0
  14. data/lib/arkana/templates/kotlin/build.gradle.kts.erb +18 -0
  15. data/lib/arkana/templates/kotlin/build_kmp.gradle.kts.erb +28 -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/{interfaces_readme.erb → swift/interfaces_readme.erb} +1 -1
  20. data/lib/arkana/version.rb +1 -1
  21. data/lib/arkana.rb +9 -1
  22. metadata +18 -12
  23. data/lib/arkana/helpers/enumerable.rb +0 -16
  24. /data/lib/arkana/templates/{arkana.podspec.erb → swift/arkana.podspec.erb} +0 -0
  25. /data/lib/arkana/templates/{arkana_tests.swift.erb → swift/arkana_tests.swift.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: 1f589f9e9d3ccd550915af3bb90a46717e385e5e7691d1a92a69da3352f187eb
4
- data.tar.gz: 4871dcda8ae09e6c39d2d94ec0bad3798cdb6b9dec6a1b50e4b7fc6e97231980
3
+ metadata.gz: 0eebedf149a0b63a1a27a4e7c788918a8c213f65af6ea50a33caae5c01361fa7
4
+ data.tar.gz: 255c72585235c23af030656e44ef212dd6efccf7873fe69aa6af078369529a64
5
5
  SHA512:
6
- metadata.gz: 2dbf5f95c13a18d75f82c0598818e0e4b580e10cdbdf9a10c283c6151a7c1b94b21cd740f849dcf70351ace776a50741c320d22871ab1bda086a29136e715c52
7
- data.tar.gz: 42ac12f877d80cc5f6e858db44fb78106e260fd1775e43bd7e3c82b8bea1206acb9ab174c4e00249d57c2990b0225593ea81bf7790a2b661171025a2f6c2b92e
6
+ metadata.gz: df602733de90c8035aa1709b5271f7f6b12cbca6c1fd67a53f6dc1ddc17cdcc6d73f63ee5ed5d6a3040d8cc06c0c3842e724e40a8c50a4799c4d211a1af162ac
7
+ data.tar.gz: f088cc8cacfed6c9561c3db34fd3a9161624ca29f5c89db1dc50db125e38e22216f06581ad9034824f8611121d03051607ea02b0b99c7ec34645f81bf2820a25
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "yaml"
3
+ require "yaml" unless defined?(YAML)
4
4
  require_relative "models/config"
5
5
  require_relative "helpers/ui"
6
6
 
@@ -14,6 +14,7 @@ module ConfigParser
14
14
  config = Config.new(yaml)
15
15
  config.include_environments(arguments.include_environments)
16
16
  config.current_flavor = arguments.flavor
17
+ config.current_lang = arguments.lang
17
18
  config.dotenv_filepath = arguments.dotenv_filepath
18
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)
19
20
  config
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "arkana/helpers/string"
4
- require "arkana/helpers/enumerable"
3
+ require_relative "helpers/string"
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
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "erb" unless defined?(Erb)
4
+ require "fileutils" unless defined?(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
+
13
+ source_set = config.is_kotlin_multiplatform_module ? "commonMain" : "main"
14
+ test_set = config.is_kotlin_multiplatform_module ? "commonTest" : "test"
15
+
16
+ kotlin_sources_dir = File.join(kotlin_module_dir, "src", source_set, config.kotlin_sources_path, config.kotlin_package_name.split("."))
17
+ kotlin_tests_dir = File.join(kotlin_module_dir, "src", test_set, config.kotlin_sources_path, config.kotlin_package_name.split("."))
18
+
19
+ if config.should_generate_gradle_build_file
20
+ set_up_kotlin_module(kotlin_module_dir, template_arguments, config)
21
+ end
22
+
23
+ set_up_kotlin_interfaces(kotlin_sources_dir, template_arguments, config)
24
+ set_up_kotlin_classes(kotlin_sources_dir, kotlin_tests_dir, template_arguments, config)
25
+ end
26
+
27
+ def self.set_up_kotlin_module(path, template_arguments, config)
28
+ dirname = File.dirname(__FILE__)
29
+ sources_dir = path
30
+ readme_template = File.read("#{dirname}/templates/readme.erb")
31
+ gradle_template_file = config.is_kotlin_multiplatform_module ? "build_kmp.gradle.kts.erb" : "build.gradle.kts.erb"
32
+ source_template = File.read("#{dirname}/templates/kotlin/#{gradle_template_file}")
33
+ FileUtils.mkdir_p(path)
34
+ render(readme_template, template_arguments, File.join(path, "README.md"))
35
+ render(source_template, template_arguments, File.join(sources_dir, "build.gradle.kts"))
36
+ end
37
+
38
+ def self.set_up_kotlin_interfaces(path, template_arguments, config)
39
+ dirname = File.dirname(__FILE__)
40
+ sources_dir = path
41
+ source_template = File.read("#{dirname}/templates/kotlin/arkana_protocol.kt.erb")
42
+ FileUtils.mkdir_p(path)
43
+ render(source_template, template_arguments, File.join(sources_dir, "#{config.namespace}Environment.kt"))
44
+ end
45
+
46
+ def self.set_up_kotlin_classes(sources_dir, tests_dir, template_arguments, config)
47
+ dirname = File.dirname(__FILE__)
48
+ source_template = File.read("#{dirname}/templates/kotlin/arkana.kt.erb")
49
+ tests_template = File.read("#{dirname}/templates/kotlin/arkana_tests.kt.erb")
50
+ FileUtils.mkdir_p(sources_dir)
51
+ FileUtils.mkdir_p(tests_dir) if config.should_generate_unit_tests
52
+ render(source_template, template_arguments, File.join(sources_dir, "#{config.namespace}.kt"))
53
+ render(tests_template, template_arguments, File.join(tests_dir, "#{config.namespace}Test.kt")) if config.should_generate_unit_tests
54
+ end
55
+
56
+ def self.render(template, template_arguments, destination_file)
57
+ renderer = ERB.new(template, trim_mode: ">") # Don't automatically add newlines at the end of each template tag
58
+ result = renderer.result(template_arguments.get_binding)
59
+ File.write(destination_file, result)
60
+ end
61
+ end
@@ -12,6 +12,8 @@ class Arguments
12
12
  attr_reader :flavor
13
13
  # @returns [Array<string>]
14
14
  attr_reader :include_environments
15
+ # @returns [string]
16
+ attr_reader :lang
15
17
 
16
18
  def initialize
17
19
  # Default values
@@ -19,6 +21,7 @@ class Arguments
19
21
  @dotenv_filepath = ".env" if File.exist?(".env")
20
22
  @flavor = nil
21
23
  @include_environments = nil
24
+ @lang = "swift"
22
25
 
23
26
  OptionParser.new do |opt|
24
27
  opt.on("-c", "--config-filepath /path/to/your/.arkana.yml", "Path to your config file. Defaults to '.arkana.yml'") do |o|
@@ -30,9 +33,12 @@ class Arguments
30
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|
31
34
  @flavor = o
32
35
  end
33
- 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 ommitted, Arkana generate secrets for all environments.") do |o|
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|
34
37
  @include_environments = o.split(",")
35
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
36
42
  end.parse!
37
43
  end
38
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,19 @@ 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
37
+ # @returns [boolean]
38
+ attr_reader :is_kotlin_multiplatform_module
29
39
 
30
40
  # @returns [string]
31
41
  attr_accessor :current_flavor
32
42
  # @returns [string]
33
43
  attr_accessor :dotenv_filepath
44
+ # @returns [string]
45
+ attr_accessor :current_lang
34
46
 
35
47
  # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
36
48
  def initialize(yaml)
@@ -42,6 +54,8 @@ class Config
42
54
  @import_name = yaml["import_name"] || default_name
43
55
  @pod_name = yaml["pod_name"] || default_name
44
56
  @result_path = yaml["result_path"] || default_name
57
+ @kotlin_package_name = yaml["kotlin_package_name"] || "com.arkanakeys"
58
+ @kotlin_sources_path = yaml["kotlin_sources_path"] || "kotlin"
45
59
  @flavors = yaml["flavors"] || []
46
60
  @swift_declaration_strategy = yaml["swift_declaration_strategy"] || "let"
47
61
  @should_generate_unit_tests = yaml["should_generate_unit_tests"]
@@ -49,6 +63,11 @@ class Config
49
63
  @package_manager = yaml["package_manager"] || "spm"
50
64
  @should_cocoapods_cross_import_modules = yaml["should_cocoapods_cross_import_modules"]
51
65
  @should_cocoapods_cross_import_modules = true if @should_cocoapods_cross_import_modules.nil?
66
+ @should_generate_gradle_build_file = yaml["should_generate_gradle_build_file"]
67
+ @should_generate_gradle_build_file = true if @should_generate_gradle_build_file.nil?
68
+ @kotlin_jvm_toolchain_version = yaml["kotlin_jvm_toolchain_version"] || 11
69
+ @is_kotlin_multiplatform_module = yaml["is_kotlin_multiplatform_module"]
70
+ @is_kotlin_multiplatform_module = false if @should_generate_gradle_build_file.nil?
52
71
  end
53
72
  # rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
54
73
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "arkana/models/secret"
3
+ require_relative "secret"
4
4
 
5
5
  # A class that defines template arguments in a language-agnostic form.
6
6
  class TemplateArguments
@@ -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.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "securerandom"
3
+ require "securerandom" unless defined?(SecureRandom)
4
4
  require_relative "models/salt"
5
5
 
6
6
  # Responsible for generating the salt.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "erb"
4
- require "fileutils"
3
+ require "erb" unless defined?(Erb)
4
+ require "fileutils" unless defined?(FileUtils)
5
5
  require_relative "helpers/string"
6
6
 
7
7
  # Responsible for generating Swift source and test files.
@@ -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_relative "lib/arkana/helpers/string" %>
2
+ <% require_relative "lib/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.decodeToString()
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_relative "lib/arkana/helpers/string" %>
2
+ <% require_relative "lib/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_relative "lib/arkana/helpers/string" %>
2
+ <% require_relative "lib/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
+ }
@@ -0,0 +1,28 @@
1
+ // DO NOT MODIFY
2
+ // Automatically generated by Arkana (https://github.com/rogerluan/arkana)
3
+
4
+ plugins {
5
+ id("org.jetbrains.kotlin.multiplatform")
6
+ }
7
+
8
+ kotlin {
9
+ jvm()
10
+ iosX64()
11
+ iosArm64()
12
+ iosSimulatorArm64()
13
+ linuxX64()
14
+ js {
15
+ browser()
16
+ nodejs()
17
+ }
18
+
19
+ sourceSets {
20
+ val commonTest by getting {
21
+ dependencies {
22
+ implementation(kotlin("test"))
23
+ }
24
+ }
25
+ }
26
+
27
+ jvmToolchain(<%= @kotlin_jvm_toolchain_version %>)
28
+ }
@@ -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_relative "lib/arkana/helpers/string" %>
2
+ <% require_relative "lib/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_relative "lib/arkana/helpers/string" %>
2
+ <% require_relative "lib/arkana/helpers/swift_template_helper" %>
3
3
  // DO NOT MODIFY
4
4
  // Automatically generated by Arkana (https://github.com/rogerluan/arkana)
5
5
 
@@ -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.6.0"
4
+ VERSION = "2.1.0"
5
5
  end
data/lib/arkana.rb CHANGED
@@ -7,6 +7,7 @@ require_relative "arkana/helpers/ui"
7
7
  require_relative "arkana/models/template_arguments"
8
8
  require_relative "arkana/salt_generator"
9
9
  require_relative "arkana/swift_code_generator"
10
+ require_relative "arkana/kotlin_code_generator"
10
11
  require_relative "arkana/version"
11
12
 
12
13
  # Top-level namespace for Arkana's execution entry point. When ran from CLI, `Arkana.run` is what is invoked.
@@ -43,7 +44,14 @@ module Arkana
43
44
  config: config,
44
45
  salt: salt,
45
46
  )
46
- 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(
47
55
  template_arguments: template_arguments,
48
56
  config: config,
49
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.6.0
4
+ version: 2.1.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-12-04 00:00:00.000000000 Z
11
+ date: 2024-06-11 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,20 @@ 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
87
+ - lib/arkana/templates/kotlin/build_kmp.gradle.kts.erb
90
88
  - lib/arkana/templates/readme.erb
89
+ - lib/arkana/templates/swift/arkana.podspec.erb
90
+ - lib/arkana/templates/swift/arkana.swift.erb
91
+ - lib/arkana/templates/swift/arkana_protocol.swift.erb
92
+ - lib/arkana/templates/swift/arkana_tests.swift.erb
93
+ - lib/arkana/templates/swift/interfaces.podspec.erb
94
+ - lib/arkana/templates/swift/interfaces_package.swift.erb
95
+ - lib/arkana/templates/swift/interfaces_readme.erb
96
+ - lib/arkana/templates/swift/package.swift.erb
91
97
  - lib/arkana/version.rb
92
98
  homepage: https://github.com/rogerluan/arkana
93
99
  licenses:
@@ -112,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
118
  - !ruby/object:Gem::Version
113
119
  version: '0'
114
120
  requirements: []
115
- rubygems_version: 3.4.10
121
+ rubygems_version: 3.5.3
116
122
  signing_key:
117
123
  specification_version: 4
118
124
  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