@logrocket/react-native 1.35.2 → 1.37.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.
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
16
16
  s.source_files = "ios/**/*.{h,c,m,swift}"
17
17
  s.requires_arc = true
18
18
 
19
- s.dependency "LogRocket", "1.35.2"
19
+ s.dependency "LogRocket", "1.37.0"
20
20
  s.dependency "React"
21
21
  end
22
22
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@logrocket/react-native",
3
3
  "title": "Logrocket Native Module",
4
- "version": "1.35.2",
4
+ "version": "1.37.0",
5
5
  "description": "LogRocket SDK for react-native",
6
6
  "typings": "types.d.ts",
7
7
  "files": [
@@ -14,7 +14,8 @@
14
14
  "logrocket-react-native.podspec",
15
15
  "types.d.ts",
16
16
  "app.plugin.js",
17
- "plugin/withLogRocket.js"
17
+ "plugin/withLogRocket.js",
18
+ "scripts/asset-upload-script.rb"
18
19
  ],
19
20
  "scripts": {
20
21
  "test": "jest"
@@ -1,39 +1,229 @@
1
1
  const {
2
2
  withProjectBuildGradle,
3
3
  createRunOncePlugin,
4
+ withAppBuildGradle,
5
+ withXcodeProject,
4
6
  } = require('@expo/config-plugins');
7
+ const {
8
+ getXCConfigurationListEntries,
9
+ getBuildConfigurationsForListId,
10
+ } = require('@expo/config-plugins/build/ios/utils/Xcodeproj');
11
+ const {
12
+ removeGeneratedContents,
13
+ createGeneratedHeaderComment,
14
+ } = require('@expo/config-plugins/build/utils/generateCode');
15
+ const { withBuildProperties } = require('expo-build-properties');
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+
19
+ const LOGROCKET_MAVEN_URL = 'maven { url "https://storage.googleapis.com/logrocket-maven/" }';
20
+ const LOGROCKET_DEPENDENCY_CLASSPATH = 'classpath "com.logrocket.gradle:android:0.3.0"';
21
+ const LOGROCKET_PLUGIN = 'apply plugin: \'com.logrocket.gradle.android\'';
22
+
23
+ const buildscriptRepositoriesRegex = new RegExp(/buildscript\s*{.*?repositories\s*{.*?(?=\n\s*})/, 'sg');
24
+ const buildscriptDependenciesRegex = new RegExp(/buildscript\s*{.*?dependencies\s*{.*?(?=\n\s*})/, 'sg');
25
+
26
+ function createGeneratedHeaderAndFooter(tag) {
27
+ return {
28
+ header: createGeneratedHeaderComment(tag, tag, '//'),
29
+ footer: `// @generated end ${tag}`,
30
+ };
31
+ }
5
32
 
6
- // Because we need the package to be added AFTER the React and Google maven packages, we create a
7
- // new allprojects. It's ok to have multiple allprojects.repositories, so we create a new one since
8
- // it's cheaper than tokenizing the existing block to find the correct place to insert.
9
- const gradleMaven =
10
- 'allprojects { repositories { maven { url "https://storage.googleapis.com/logrocket-maven/" } } }';
33
+ function modProjectGradle(buildGradle) {
34
+ let modifiedGradle = buildGradle;
11
35
 
12
- function setGradleMaven(buildGradle) {
13
- if (buildGradle.includes('logrocket-maven')) {
14
- return buildGradle;
36
+ // insert repository
37
+ removeGeneratedContents(modifiedGradle, 'logrocket-buildscript-repositories');
38
+ if (buildscriptRepositoriesRegex.exec(modifiedGradle) !== null) {
39
+ const { header, footer } = createGeneratedHeaderAndFooter('logrocket-buildscript-repositories');
40
+ modifiedGradle = `
41
+ ${modifiedGradle.slice(0, buildscriptRepositoriesRegex.lastIndex)}
42
+ ${header}
43
+ ${LOGROCKET_MAVEN_URL}
44
+ ${footer}
45
+ ${modifiedGradle.slice(buildscriptRepositoriesRegex.lastIndex)}`;
15
46
  }
16
47
 
17
- return `${buildGradle}\n${gradleMaven}\n`;
48
+ // insert dependency
49
+ removeGeneratedContents(modifiedGradle, 'logrocket-buildscript-dependencies');
50
+ if (buildscriptDependenciesRegex.exec(modifiedGradle) !== null) {
51
+ const { header, footer } = createGeneratedHeaderAndFooter('logrocket-buildscript-dependencies');
52
+ modifiedGradle = `
53
+ ${modifiedGradle.slice(0, buildscriptDependenciesRegex.lastIndex)}
54
+ ${header}
55
+ ${LOGROCKET_DEPENDENCY_CLASSPATH}
56
+ ${footer}
57
+ ${modifiedGradle.slice(buildscriptDependenciesRegex.lastIndex)}`;
58
+ }
59
+
60
+ return modifiedGradle;
18
61
  }
19
62
 
20
- const withAndroidLogRocketMaven = config => {
21
- return withProjectBuildGradle(config, gradleConfig => {
63
+ function modApplicationGradle(buildGradle, pluginProps) {
64
+ let modifiedGradle = buildGradle;
65
+
66
+ // insert plugin
67
+ removeGeneratedContents(modifiedGradle, 'logrocket-plugin');
68
+ const comments = createGeneratedHeaderAndFooter('logrocket-plugin');
69
+ modifiedGradle += `
70
+ ${comments.header}
71
+ ${LOGROCKET_PLUGIN}
72
+ ${comments.footer}
73
+ `;
74
+
75
+ // insert logrocket config if any plugin props were passed in
76
+ removeGeneratedContents(modifiedGradle, 'logrocket-config');
77
+ if (pluginProps.android.assetCapture) {
78
+ const { header, footer } = createGeneratedHeaderAndFooter('logrocket-config');
79
+ const assetCapture = pluginProps.android.assetCapture;
80
+ let configSection = 'logrocket {\n';
81
+ if (assetCapture.apiKey) {
82
+ configSection += `\tapiKey = "${assetCapture.apiKey}"\n`;
83
+ }
84
+ if (assetCapture.apiHost) {
85
+ configSection += `\tapiHost = "${assetCapture.apiHost}"\n`;
86
+ }
87
+ if (assetCapture.enabledVariants && Array.isArray(assetCapture.enabledVariants)) {
88
+ const enabledVariants = assetCapture.enabledVariants;
89
+ configSection += `\tenabledVariants = [${enabledVariants.map(e => `"${e}"`).join(', ')}].toSet()\n`;
90
+ }
91
+ configSection += '}';
92
+ modifiedGradle = `
93
+ ${modifiedGradle}
94
+ ${header}
95
+ ${configSection}
96
+ ${footer}
97
+ `;
98
+ }
99
+
100
+ return modifiedGradle;
101
+ }
102
+
103
+ const withAndroidLogRocket = (config, pluginProps) => {
104
+ // eslint-disable-next-line no-param-reassign
105
+ config = withProjectBuildGradle(config, gradleConfig => {
22
106
  if (gradleConfig.modResults.language === 'groovy') {
23
107
  // eslint-disable-next-line no-param-reassign
24
- gradleConfig.modResults.contents = setGradleMaven(gradleConfig.modResults.contents);
108
+ gradleConfig.modResults.contents = modProjectGradle(gradleConfig.modResults.contents);
25
109
  } else {
26
110
  throw new Error(
27
- 'Cannot add LogRocket maven respository because the build.gradle is not groovy'
111
+ 'Cannot add LogRocket gradle config because the project build.gradle is not groovy'
28
112
  );
29
113
  }
114
+ return gradleConfig;
115
+ });
30
116
 
117
+ // eslint-disable-next-line no-param-reassign
118
+ config = withAppBuildGradle(config, gradleConfig => {
119
+ if (gradleConfig.modResults.language === 'groovy') {
120
+ // eslint-disable-next-line no-param-reassign
121
+ gradleConfig.modResults.contents = modApplicationGradle(gradleConfig.modResults.contents, pluginProps);
122
+ } else {
123
+ throw new Error(
124
+ 'Cannot add LogRocket gradle config because the application build.gradle is not groovy'
125
+ );
126
+ }
31
127
  return gradleConfig;
32
128
  });
129
+
130
+ return config;
33
131
  };
34
132
 
35
- const withLogRocket = config => {
36
- return withAndroidLogRocketMaven(config);
133
+ const withIosLogRocket = (config, pluginProps) => {
134
+ // eslint-disable-next-line no-param-reassign
135
+ config = withXcodeProject(config, xcodeProjConfig => {
136
+ const xcodeProject = xcodeProjConfig.modResults;
137
+ const LOGROCKET_UPLOAD_SCRIPT = fs.readFileSync(
138
+ path.resolve(__dirname, '../scripts/asset-upload-script.rb'), 'utf-8');
139
+
140
+ // add run script build phase to run ruby script
141
+ const logRocketBuildPhase = xcodeProject.pbxItemByComment(
142
+ 'LogRocket Custom Font Capture',
143
+ 'PBXShellScriptBuildPhase'
144
+ );
145
+ if (!logRocketBuildPhase) {
146
+ xcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'LogRocket Custom Font Capture', null, {
147
+ shellPath: '"/usr/bin/env ruby"',
148
+ shellScript: LOGROCKET_UPLOAD_SCRIPT,
149
+ });
150
+ } else {
151
+ logRocketBuildPhase.shellPath = '"/usr/bin/env ruby"';
152
+ logRocketBuildPhase.shellScript = JSON.stringify(LOGROCKET_UPLOAD_SCRIPT);
153
+ }
154
+
155
+ // configure environment variables
156
+ getXCConfigurationListEntries(xcodeProject).forEach(configList => {
157
+ getBuildConfigurationsForListId(xcodeProject, configList[0]).forEach(configSection => {
158
+ const buildConfig = configSection[1];
159
+ if (pluginProps.ios.assetCapture) {
160
+ const assetCapture = pluginProps.ios.assetCapture;
161
+ if (assetCapture.apiKey) {
162
+ buildConfig.buildSettings.LOGROCKET_API_KEY = `"${assetCapture.apiKey}"`;
163
+ }
164
+ if (assetCapture.apiHost) {
165
+ buildConfig.buildSettings.LOGROCKET_API_HOST = `"${assetCapture.apiHost}"`;
166
+ }
167
+ if (assetCapture.assetDirectory) {
168
+ buildConfig.buildSettings.LOGROCKET_ASSET_DIR = `"${assetCapture.assetDirectory}"`;
169
+ }
170
+ if (assetCapture.cliPath) {
171
+ buildConfig.buildSettings.LOGROCKET_CLI_PATH = `"${assetCapture.cliPath}"`;
172
+ }
173
+ if (assetCapture.enabledBuildConfigs && Array.isArray(assetCapture.enabledBuildConfigs)) {
174
+ const enabledBuildConfigs = assetCapture.enabledBuildConfigs;
175
+ buildConfig.buildSettings.LOGROCKET_ENABLED_BUILD_CONFIGS = `"${enabledBuildConfigs.join(',')}"`;
176
+ }
177
+ }
178
+ });
179
+ });
180
+
181
+ return xcodeProjConfig;
182
+ });
183
+ return config;
184
+ };
185
+
186
+ /*
187
+ pluginProps schema:
188
+ {
189
+ "android": {
190
+ "assetCapture": {
191
+ "apiKey": "apphub:android:123abc", REQUIRED
192
+ "apiHost": "http://localhost:8000",
193
+ "enabledVariants": ["debug", "release"]
194
+ }
195
+ },
196
+ "ios": {
197
+ "assetCapture": {
198
+ "apiKey": "apphub:ios:123abc", REQUIRED
199
+ "apiHost": "http://localhost:8000",
200
+ "assetDirectory": "example-directory/logrocket", REQUIRED
201
+ "cliPath": "example-path/logrocket", REQUIRED (if logrocket-cli hasn't been added to $PATH)
202
+ "enabledBuildConfigs": ["Debug", "Release"]
203
+ }
204
+ }
205
+ }
206
+ */
207
+
208
+ const withLogRocket = (config, pluginProps = {}) => {
209
+ // eslint-disable-next-line no-param-reassign
210
+ config = withBuildProperties(config, {
211
+ android: {
212
+ extraMavenRepos: ['https://storage.googleapis.com/logrocket-maven/'],
213
+ },
214
+ });
215
+
216
+ if (pluginProps.android && pluginProps.android.assetCapture) {
217
+ // eslint-disable-next-line no-param-reassign
218
+ config = withAndroidLogRocket(config, pluginProps);
219
+ }
220
+
221
+ if (pluginProps.ios && pluginProps.ios.assetCapture) {
222
+ // eslint-disable-next-line no-param-reassign
223
+ config = withIosLogRocket(config, pluginProps);
224
+ }
225
+
226
+ return config;
37
227
  };
38
228
 
39
229
  module.exports = createRunOncePlugin(withLogRocket, 'logrocket');
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'json'
5
+
6
+ # Ensure the font data file is freshly generated on each build
7
+ app_build_resources_dir = "#{ENV['BUILT_PRODUCTS_DIR']}/#{ENV['UNLOCALIZED_RESOURCES_FOLDER_PATH']}"
8
+ output_file = "#{app_build_resources_dir}/lr_custom_fonts_data.json"
9
+ if File.exist?(output_file)
10
+ File.delete(output_file)
11
+ end
12
+
13
+
14
+ # Check whether LogRocket asset upload is enabled for this build
15
+ current_build_config = ENV['CONFIGURATION']
16
+ enabled_build_configs = ENV['LOGROCKET_ENABLED_BUILD_CONFIGS']&.split(',')
17
+
18
+ unless enabled_build_configs&.include?(current_build_config) || current_build_config == 'Release'
19
+ puts "LogRocket custom asset upload is not enabled for this build."
20
+ exit 0
21
+ end
22
+
23
+ # Ensure configuration is set that allows script to find the downloaded LogRocket CLI for execution
24
+ LOGROCKET_CLI_PATH = ENV['LOGROCKET_CLI_PATH'] || `which logrocket-cli`.strip
25
+ if LOGROCKET_CLI_PATH.empty?
26
+ warn 'Error: LOGROCKET_CLI_PATH is not set and logrocket-cli was not found on $PATH'
27
+ exit 1
28
+ end
29
+
30
+ # Ensure configuration is set to authorize asset upload for your LogRocket application
31
+ unless ENV['LOGROCKET_API_KEY']
32
+ warn 'Error: LOGROCKET_API_KEY is not set'
33
+ exit 1
34
+ end
35
+
36
+ # Ensure configuration is set that allows LogRocket CLI to find custom font files
37
+ unless ENV['LOGROCKET_ASSET_DIR']
38
+ warn 'Error: LOGROCKET_ASSET_DIR is not set'
39
+ exit 1
40
+ end
41
+
42
+ # Execute asset_upload CLI command and collect output
43
+ cli_cmd = "#{LOGROCKET_CLI_PATH} asset_upload #{ENV['LOGROCKET_ASSET_DIR']}"
44
+ cli_output = `#{cli_cmd}`
45
+
46
+
47
+ # Parse CLI output to report any errors or generate the build resource used by the LogRocket SDK
48
+ urls = []
49
+ cli_output.each_line do |line|
50
+ data = begin
51
+ JSON.parse(line)
52
+ rescue StandardError
53
+ nil
54
+ end
55
+ next unless data
56
+
57
+ case data['level']
58
+ when 'info'
59
+ if data['url']
60
+ urls << data['url']
61
+ else
62
+ warn "Failed to retrieve cached url for #{data['filepath']}"
63
+ end
64
+ when 'error'
65
+ warn "Error: #{data['message']}"
66
+ exit 1
67
+ else
68
+ warn "Unknown level for LogRocket CLI asset-upload output: #{data['level']}"
69
+ exit 1
70
+ end
71
+ end
72
+
73
+ if urls.empty?
74
+ warn 'No valid custom font assets found for upload'
75
+ else
76
+ Dir.mkdir(app_build_resources_dir) unless Dir.exist?(app_build_resources_dir)
77
+
78
+ json_data = { urls: urls }.to_json
79
+ File.write(output_file, json_data)
80
+ end
81
+
82
+ exit 0