evva 0.1.4.1 → 0.2.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 +5 -5
- data/.gitignore +1 -2
- data/.rspec +0 -1
- data/.ruby-version +1 -0
- data/.travis.yml +1 -0
- data/Gemfile +10 -8
- data/Gemfile.lock +5 -6
- data/README.md +10 -0
- data/Rakefile +9 -0
- data/changelog.md +18 -1
- data/evva.gemspec +0 -3
- data/evva_config.yml +5 -1
- data/lib/evva/android_generator.rb +72 -53
- data/lib/evva/config.rb +13 -2
- data/lib/evva/google_sheet.rb +49 -46
- data/lib/evva/swift_generator.rb +61 -61
- data/lib/evva/version.rb +2 -2
- data/lib/evva.rb +5 -7
- data/spec/fixtures/sample_public_enums.csv +3 -0
- data/spec/fixtures/sample_public_events.csv +4 -0
- data/spec/fixtures/sample_public_people_properties.csv +3 -0
- data/spec/fixtures/test.yml +5 -2
- data/spec/lib/evva/android_generator_spec.rb +117 -99
- data/spec/lib/evva/config_spec.rb +8 -4
- data/spec/lib/evva/google_sheet_spec.rb +44 -74
- data/spec/lib/evva/swift_generator_spec.rb +100 -69
- metadata +9 -38
- data/lib/evva/data_source.rb +0 -23
- data/spec/fixtures/sample_public_enums.html +0 -1
- data/spec/fixtures/sample_public_info.html +0 -1
- data/spec/fixtures/sample_public_people_properties.html +0 -1
- data/spec/fixtures/sample_public_sheet.html +0 -1
- data/spec/lib/evva/data_source_spec.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c9078e38ca6bba5b85a3349fb9e1c3f9c31b8de357080ffb1ab105e6bcbbdaa1
|
4
|
+
data.tar.gz: 16b264637125fafdc14a991a9cb984e440b948bdc7d934776329b8aa8ef2d89f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6efc1abd4ea8d72f7ac2edeccbf111deac25922fa0b1464d754d21e7bfef921efffddd228bb6d6913f3b64a4acfcd8763082f0b36b16e85e28b930d933df879c
|
7
|
+
data.tar.gz: 77a4ad5df7074b646def8c880654b551fcde2e10523e3dec622d202fba48ac7bdda6d1a882abcd5c54bc2e6175b2bb68a52c30ab77d1c522f29362bc9a297db3
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.7.3
|
data/.travis.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
language: ruby
|
data/Gemfile
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
|
-
ruby '2.
|
2
|
+
ruby '2.7.3'
|
3
3
|
|
4
4
|
gem 'colorize'
|
5
|
-
gem 'rubocop'
|
6
5
|
gem 'safe_yaml'
|
7
|
-
gem 'xml-simple'
|
8
6
|
|
9
|
-
|
10
|
-
gem '
|
11
|
-
gem '
|
12
|
-
gem '
|
13
|
-
gem '
|
7
|
+
group :test do
|
8
|
+
gem 'rake'
|
9
|
+
gem 'rspec'
|
10
|
+
gem 'rspec-its'
|
11
|
+
gem 'simplecov', require: false, group: :test
|
12
|
+
gem 'simplecov-rcov', require: false
|
13
|
+
gem 'webmock', '~> 1.20'
|
14
|
+
gem 'rubocop'
|
15
|
+
end
|
data/Gemfile.lock
CHANGED
@@ -10,7 +10,7 @@ GEM
|
|
10
10
|
diff-lcs (1.3)
|
11
11
|
docile (1.1.5)
|
12
12
|
hashdiff (0.3.7)
|
13
|
-
json (2.
|
13
|
+
json (2.3.0)
|
14
14
|
parallel (1.12.0)
|
15
15
|
parser (2.4.0.0)
|
16
16
|
ast (~> 2.2)
|
@@ -18,7 +18,7 @@ GEM
|
|
18
18
|
public_suffix (3.0.0)
|
19
19
|
rainbow (2.2.2)
|
20
20
|
rake
|
21
|
-
rake (12.
|
21
|
+
rake (12.3.3)
|
22
22
|
rspec (3.7.0)
|
23
23
|
rspec-core (~> 3.7.0)
|
24
24
|
rspec-expectations (~> 3.7.0)
|
@@ -56,13 +56,13 @@ GEM
|
|
56
56
|
addressable (>= 2.3.6)
|
57
57
|
crack (>= 0.3.2)
|
58
58
|
hashdiff
|
59
|
-
xml-simple (1.1.5)
|
60
59
|
|
61
60
|
PLATFORMS
|
62
61
|
ruby
|
63
62
|
|
64
63
|
DEPENDENCIES
|
65
64
|
colorize
|
65
|
+
rake
|
66
66
|
rspec
|
67
67
|
rspec-its
|
68
68
|
rubocop
|
@@ -70,10 +70,9 @@ DEPENDENCIES
|
|
70
70
|
simplecov
|
71
71
|
simplecov-rcov
|
72
72
|
webmock (~> 1.20)
|
73
|
-
xml-simple
|
74
73
|
|
75
74
|
RUBY VERSION
|
76
|
-
ruby 2.
|
75
|
+
ruby 2.7.3p183
|
77
76
|
|
78
77
|
BUNDLED WITH
|
79
|
-
|
78
|
+
2.2.26
|
data/README.md
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
Evva
|
2
|
+
========
|
3
|
+
|
4
|
+
[](https://travis-ci.org/hole19/evva?branch=master)
|
5
|
+
[](http://rubygems.org/gems/evva "View this project in Rubygems")
|
6
|
+
|
7
|
+
Evva automatically generates code for triggering events based on a Google Sheets specification. It generated code for both iOS (Swift) and Android (Kotlin).
|
2
8
|
|
3
9
|
# Instalation
|
4
10
|
|
@@ -19,9 +25,13 @@ Evva
|
|
19
25
|
data_source:
|
20
26
|
type: google_sheet
|
21
27
|
sheet_id: <GOOGLE-DRIVE-SHEET-ID>
|
28
|
+
events_url: <GOOGLE-DRIVE-EVENTS-SHEET-URL>
|
29
|
+
people_properties_url: <GOOGLE-DRIVE-PEOPLE-PROPERTIES-SHEET-URL>
|
30
|
+
enum_classes_url: <GOOGLE-DRIVE-ENUM-CLASSES-SHEET-URL>
|
22
31
|
|
23
32
|
out_path: /folder/where/analytics/classes/are
|
24
33
|
event_file_name: /file/with/tracking/functions
|
25
34
|
event_enum_file_name: /file/with/event/names
|
26
35
|
people_file_name: /file/with/people/properties
|
36
|
+
special_enum_file_name: //file/with/special/enum/properties/
|
27
37
|
```
|
data/Rakefile
ADDED
data/changelog.md
CHANGED
@@ -1,4 +1,20 @@
|
|
1
1
|
# Change Log
|
2
|
+
|
3
|
+
## [0.2.0] - 2021/08/30
|
4
|
+
- Google Spreadsheet option stopped working due to a change in the API. This version fixes that.
|
5
|
+
|
6
|
+
Note: You'll need a new setup. View README.
|
7
|
+
|
8
|
+
## [0.1.4.4] - 2019-02-04
|
9
|
+
- Adds support for dynamic android package name
|
10
|
+
|
11
|
+
## [0.1.4.3] - 2018-10-12
|
12
|
+
- Fixes swift and kotlin tabs, indentation and property names
|
13
|
+
- Merges all special enums in a single file
|
14
|
+
|
15
|
+
## [0.1.4.2] - 2018-02-14
|
16
|
+
- Replaces Swift headers
|
17
|
+
|
2
18
|
## [0.1.4.1] - 2018-02-08
|
3
19
|
- DRYs methods in swift event generation
|
4
20
|
|
@@ -17,4 +33,5 @@
|
|
17
33
|
- Fixes mismatch between file name and class name generated.
|
18
34
|
|
19
35
|
## [0.1.0] - 2017/10/26
|
20
|
-
- Initial Release.
|
36
|
+
- Initial Release.
|
37
|
+
|
data/evva.gemspec
CHANGED
data/evva_config.yml
CHANGED
@@ -3,8 +3,12 @@ type: iOS
|
|
3
3
|
data_source:
|
4
4
|
type: google_sheet
|
5
5
|
sheet_id: 1LaJd68os3g_GFlerogC64grNIlXb2iukMznOvdml7A4
|
6
|
+
events_url: https://path-to-csv
|
7
|
+
people_properties_url: https://path-to-csv
|
8
|
+
enum_classes_url: https://path-to-csv
|
6
9
|
|
7
10
|
out_path: analytics
|
8
11
|
event_file_name: MixpanelAnalytics
|
9
12
|
event_enum_file_name: MixpanelEvent
|
10
|
-
people_file_name: MixpanelProperties
|
13
|
+
people_file_name: MixpanelProperties
|
14
|
+
package_name: com.hole19golf.hole19.analytics
|
@@ -1,48 +1,78 @@
|
|
1
1
|
module Evva
|
2
2
|
class AndroidGenerator
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
KOTLIN_BUNDLE_HEADER =
|
14
|
-
"package com.hole19golf.hole19.analytics\n"\
|
15
|
-
"import com.hole19golf.hole19.analytics.Event\n\n".freeze
|
16
|
-
|
17
|
-
KOTIN_PEOPLE_FUNCTIONS =
|
18
|
-
"\nopen fun updateProperties(property: MixpanelProperties, value: Any) {\n"\
|
19
|
-
"\t\tmixpanelMask.updateProperties(property.key, value)"\
|
20
|
-
"\t\n} \n"\
|
21
|
-
"\nopen fun incrementCounter(property: MixpanelProperties) {\n"\
|
22
|
-
"\t\tmixpanelMask.incrementCounter(property.key)"\
|
23
|
-
"\t\n} \n".freeze
|
3
|
+
attr_accessor :package_name
|
4
|
+
|
5
|
+
def initialize(package_name)
|
6
|
+
@package_name = package_name
|
7
|
+
end
|
8
|
+
|
9
|
+
IMPORT_EVENT = "import packagename.Event".freeze
|
10
|
+
IMPORT_MASK = "import packagename.MixpanelAnalyticsMask".freeze
|
11
|
+
IMPORT_JSON = "import org.json.JSONObject".freeze
|
24
12
|
|
25
13
|
NATIVE_TYPES = %w[Long Int String Double Float Boolean].freeze
|
26
14
|
|
27
15
|
def events(bundle, file_name)
|
28
|
-
|
29
|
-
|
30
|
-
|
16
|
+
header_footer_wrapper([IMPORT_EVENT, IMPORT_MASK, IMPORT_JSON]) do
|
17
|
+
"""open class #{file_name}(private val mask: MixpanelAnalyticsMask) {
|
18
|
+
|
19
|
+
#{bundle.map { |e| kotlin_function(e) }.join("\n\n")}
|
20
|
+
|
21
|
+
\topen fun updateProperties(property: MixpanelProperties, value: Any) {
|
22
|
+
\t\tmask.updateProperties(property.key, value)
|
23
|
+
\t}
|
24
|
+
|
25
|
+
\topen fun incrementCounter(property: MixpanelProperties) {
|
26
|
+
\t\tmask.incrementCounter(property.key)
|
27
|
+
\t}
|
28
|
+
}"""
|
31
29
|
end
|
32
|
-
event_file += KOTIN_PEOPLE_FUNCTIONS
|
33
|
-
event_file += "\n}"
|
34
30
|
end
|
35
31
|
|
36
32
|
def people_properties(people_bundle, file_name)
|
37
|
-
|
38
|
-
|
39
|
-
|
33
|
+
header_footer_wrapper do
|
34
|
+
body = "enum class MixpanelProperties(val key: String) {\n"
|
35
|
+
body << people_bundle.map { |prop| "\t#{prop.upcase}(\"#{prop}\")" }.join(",\n")
|
36
|
+
body << ";\n}"
|
37
|
+
end
|
40
38
|
end
|
41
39
|
|
42
40
|
def event_enum(bundle, file_name)
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
header_footer_wrapper([IMPORT_EVENT]) do
|
42
|
+
body = "enum class #{file_name}(override val key: String) : Event {\n"
|
43
|
+
body << bundle.map(&:event_name).map { |prop| "\t#{prop.upcase}(\"#{prop}\")" }.join(",\n")
|
44
|
+
body << ";\n}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def special_property_enums(enums)
|
49
|
+
header_footer_wrapper do
|
50
|
+
enums.map do |enum|
|
51
|
+
body = "enum class #{enum.enum_name}(val key: String) {\n"
|
52
|
+
body << enum.values.map { |vals| "\t#{vals.tr(' ', '_').upcase}(\"#{vals}\")"}.join(",\n")
|
53
|
+
body << ";\n}"
|
54
|
+
end.join("\n\n")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def imports_header(imports = [])
|
61
|
+
return unless imports.length > 0
|
62
|
+
imports.map { |ev| ev. gsub("packagename", @package_name) }
|
63
|
+
.join("\n") + "\n\n"
|
64
|
+
end
|
65
|
+
|
66
|
+
def header_footer_wrapper(imports = [])
|
67
|
+
<<-Kotlin
|
68
|
+
package #{@package_name}
|
69
|
+
|
70
|
+
#{imports_header(imports)}/**
|
71
|
+
* This file was automatically generated by evva: https://github.com/hole19/evva
|
72
|
+
*/
|
73
|
+
|
74
|
+
#{yield.gsub("\t", " ")}
|
75
|
+
Kotlin
|
46
76
|
end
|
47
77
|
|
48
78
|
def kotlin_function(event_data)
|
@@ -50,27 +80,18 @@ module Evva
|
|
50
80
|
function_arguments = event_data.properties.map { |name, type| "#{name}: #{type}" }.join(', ')
|
51
81
|
if !function_arguments.empty?
|
52
82
|
props = json_props(event_data.properties)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
83
|
+
"""\topen fun #{function_name}(#{function_arguments}) {
|
84
|
+
#{props}
|
85
|
+
\t\tmask.trackEvent(MixpanelEvent.#{event_data.event_name.upcase}, properties)
|
86
|
+
\t}"""
|
87
|
+
|
57
88
|
else
|
58
|
-
|
59
|
-
|
60
|
-
|
89
|
+
"""\topen fun #{function_name}() {
|
90
|
+
\t\tmask.trackEvent(MixpanelEvent.#{event_data.event_name.upcase})
|
91
|
+
\t}"""
|
61
92
|
end
|
62
|
-
function_body += "}\n"
|
63
|
-
end
|
64
|
-
|
65
|
-
def special_property_enum(enum)
|
66
|
-
enum_body = "package com.hole19golf.hole19.analytics\n\n"
|
67
|
-
enum_body += "enum class #{enum.enum_name}(val key: String) {\n"
|
68
|
-
enum_body += enum.values.map { |vals| "\t#{vals.tr(' ', '_').upcase}(\"#{vals}\")"}.join(",\n")
|
69
|
-
enum_body += "\n}\n"
|
70
93
|
end
|
71
94
|
|
72
|
-
private
|
73
|
-
|
74
95
|
def json_props(properties)
|
75
96
|
split_properties =
|
76
97
|
properties
|
@@ -89,12 +110,10 @@ module Evva
|
|
89
110
|
end
|
90
111
|
end
|
91
112
|
end
|
92
|
-
.map { |line| "\t\t#{line}" }
|
113
|
+
.map { |line| "\t\t\t#{line}" }
|
93
114
|
.join("\n")
|
94
115
|
|
95
|
-
|
96
|
-
+split_properties.to_s
|
97
|
-
resulting_json += "\n\t}\n"
|
116
|
+
"\t\tval properties = JSONObject().apply {\n#{split_properties}\n\t\t}"
|
98
117
|
end
|
99
118
|
|
100
119
|
def special_property?(type)
|
data/lib/evva/config.rb
CHANGED
@@ -39,6 +39,14 @@ module Evva
|
|
39
39
|
@hash[:event_enum_file_name]
|
40
40
|
end
|
41
41
|
|
42
|
+
def special_enum_file_name
|
43
|
+
@hash[:special_enum_file_name]
|
44
|
+
end
|
45
|
+
|
46
|
+
def package_name
|
47
|
+
@hash[:package_name]
|
48
|
+
end
|
49
|
+
|
42
50
|
CONFIG_STRUCT = {
|
43
51
|
type: Hash,
|
44
52
|
elements: {
|
@@ -49,7 +57,8 @@ module Evva
|
|
49
57
|
out_path: { type: String },
|
50
58
|
event_file_name: { type: String },
|
51
59
|
event_enum_file_name: { type: String },
|
52
|
-
people_file_name: { type: String }
|
60
|
+
people_file_name: { type: String },
|
61
|
+
package_name: { type: String }
|
53
62
|
}
|
54
63
|
}.freeze
|
55
64
|
|
@@ -57,7 +66,9 @@ module Evva
|
|
57
66
|
type: Hash,
|
58
67
|
elements: {
|
59
68
|
type: { type: String },
|
60
|
-
|
69
|
+
events_url: { type: String },
|
70
|
+
people_properties_url: { type: String },
|
71
|
+
enum_classes_url: { type: String },
|
61
72
|
}
|
62
73
|
}.freeze
|
63
74
|
|
data/lib/evva/google_sheet.rb
CHANGED
@@ -1,83 +1,86 @@
|
|
1
1
|
require 'net/https'
|
2
|
-
require '
|
2
|
+
require 'csv'
|
3
3
|
|
4
4
|
module Evva
|
5
5
|
class GoogleSheet
|
6
|
-
def initialize(
|
7
|
-
@
|
6
|
+
def initialize(events_url, people_properties_url, enum_classes_url)
|
7
|
+
@events_url = events_url
|
8
|
+
@people_properties_url = people_properties_url
|
9
|
+
@enum_classes_url = enum_classes_url
|
8
10
|
end
|
9
11
|
|
10
12
|
def events
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
title content link]
|
13
|
+
Logger.info("Downloading data from Google Sheet at #{@events_url}")
|
14
|
+
csv = get_csv(@events_url)
|
15
|
+
|
15
16
|
event_list = []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
event_list.push(Evva::MixpanelEvent.new(event_name, properties))
|
17
|
+
csv.each do |row|
|
18
|
+
event_name = row['Event Name']
|
19
|
+
properties = hash_parser(row['Event Properties'])
|
20
|
+
event_list << Evva::MixpanelEvent.new(event_name, properties)
|
21
21
|
end
|
22
22
|
event_list
|
23
23
|
end
|
24
24
|
|
25
25
|
def people_properties
|
26
|
-
|
26
|
+
Logger.info("Downloading data from Google Sheet at #{@people_properties_url}")
|
27
|
+
csv = get_csv(@people_properties_url)
|
28
|
+
|
27
29
|
people_list = []
|
28
|
-
|
29
|
-
|
30
|
-
raw['entry'].each do |entry|
|
31
|
-
filtered_entry = entry.reject { |c| non_language_columns.include?(c) }
|
32
|
-
value = filtered_entry['value'].first
|
30
|
+
csv.each do |row|
|
31
|
+
value = row['Property Name']
|
33
32
|
people_list << value
|
34
33
|
end
|
35
34
|
people_list
|
36
35
|
end
|
37
36
|
|
38
37
|
def enum_classes
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
Logger.info("Downloading data from Google Sheet at #{@enum_classes_url}")
|
39
|
+
csv = get_csv(@enum_classes_url)
|
40
|
+
|
42
41
|
enum_list = []
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
enum_list.push(Evva::MixpanelEnum.new(enum_name, values))
|
42
|
+
csv.each do |row|
|
43
|
+
enum_name = row['Enum Name']
|
44
|
+
values = row['Possible Values'].split(',')
|
45
|
+
enum_list << Evva::MixpanelEnum.new(enum_name, values)
|
48
46
|
end
|
49
47
|
enum_list
|
50
48
|
end
|
51
49
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
57
|
-
data = http.get(uri.path, headers)
|
58
|
-
unless data.code.to_i == 200
|
59
|
-
raise 'Cannot access sheet at #{uri} - HTTP #{data.code}'
|
60
|
-
end
|
50
|
+
private
|
51
|
+
|
52
|
+
def get_csv(url)
|
53
|
+
data = get(url)
|
61
54
|
|
62
55
|
begin
|
63
|
-
|
64
|
-
rescue
|
65
|
-
raise
|
56
|
+
CSV.parse(data, headers: true)
|
57
|
+
rescue StandardError => e
|
58
|
+
raise "Cannot parse. Expected CSV at #{url}: #{e}"
|
66
59
|
end
|
67
60
|
end
|
68
61
|
|
69
|
-
def
|
70
|
-
|
71
|
-
sheet = xml_data("https://spreadsheets.google.com/feeds/worksheets/#{sheet_id}/public/full")
|
72
|
-
url = sheet['entry'][sheet_number]['link'][0]['href']
|
73
|
-
xml_data(url)
|
74
|
-
end
|
62
|
+
def get(url, max_redirects = 1)
|
63
|
+
raise "Too may redirects" if max_redirects == -1
|
75
64
|
|
76
|
-
|
65
|
+
uri = URI(url)
|
66
|
+
|
67
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
68
|
+
http.use_ssl = true
|
69
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
70
|
+
|
71
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
72
|
+
response = http.request(request)
|
73
|
+
|
74
|
+
return get(response['location'], max_redirects - 1) if response.is_a? Net::HTTPRedirection
|
75
|
+
|
76
|
+
raise "Http Error #{response.body}" if response.code.to_i >= 400
|
77
|
+
|
78
|
+
response.body
|
79
|
+
end
|
77
80
|
|
78
81
|
def hash_parser(property_array)
|
79
82
|
h = {}
|
80
|
-
unless property_array.empty?
|
83
|
+
unless property_array.nil? || property_array.empty?
|
81
84
|
property_array.split(',').each do |prop|
|
82
85
|
split_prop = prop.split(':')
|
83
86
|
prop_name = split_prop[0].to_sym
|