capacitor-pica-network-logger 0.2.4 → 0.2.6
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.
- package/README.md +97 -78
- package/android/src/main/java/com/linakis/capacitorpicanetworklogger/LogRepositoryStore.kt +41 -5
- package/android/src/main/java/com/linakis/capacitorpicanetworklogger/LoggerConfigProvider.kt +1 -0
- package/android/src/main/java/com/linakis/capacitorpicanetworklogger/PicaNetworkLoggerPlugin.kt +18 -1
- package/ios/Plugin/InspectorLogger.swift +44 -5
- package/ios/Plugin/PicaNetworkLoggerPlugin.swift +15 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,45 +4,38 @@
|
|
|
4
4
|
|
|
5
5
|
# capacitor-pica-network-logger
|
|
6
6
|
|
|
7
|
-
Capacitor HTTP
|
|
7
|
+
A Capacitor plugin for logging and inspecting HTTP requests with native inspector UIs on iOS and Android.
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
|
11
|
-
## Tech stack
|
|
12
|
-
|
|
13
|
-
- Capacitor 7
|
|
14
|
-
- Swift (URLProtocol logging on iOS)
|
|
15
|
-
- Kotlin (HttpURLConnection reflection logging on Android)
|
|
16
|
-
- TypeScript wrapper for `@capacitor/http`
|
|
17
|
-
|
|
18
11
|
## Features
|
|
19
12
|
|
|
20
|
-
-
|
|
21
|
-
- Native inspector UI (
|
|
13
|
+
- Request/response pair logging with automatic correlation
|
|
14
|
+
- Native inspector UI on iOS (UIKit) and Android (Jetpack Compose + Material 3)
|
|
22
15
|
- Body text search with highlighting in the inspector
|
|
23
|
-
- Persistent log storage across inspector sessions
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
16
|
+
- Persistent log storage (SQLite) across inspector sessions
|
|
17
|
+
- Responsive Android layout (compact, medium, expanded breakpoints)
|
|
18
|
+
- Dark/light theme toggle
|
|
19
|
+
- Configurable header and JSON body field redaction
|
|
20
|
+
- Configurable max body size with truncation
|
|
21
|
+
- Local notifications on each completed request (tap to open inspector)
|
|
22
|
+
- Export as cURL, plain text, or HAR 1.2
|
|
23
|
+
- No-op on web -- safe to import in any environment
|
|
29
24
|
|
|
30
25
|
See the [Changelog](CHANGELOG.md) for a full history of changes.
|
|
31
26
|
|
|
32
|
-
##
|
|
27
|
+
## Platform requirements
|
|
33
28
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
| Platform | Minimum version |
|
|
30
|
+
|---|---|
|
|
31
|
+
| Capacitor | 7+ |
|
|
32
|
+
| iOS | 14.0 |
|
|
33
|
+
| Android | API 23 (Android 6.0) |
|
|
38
34
|
|
|
39
35
|
## Installation
|
|
40
36
|
|
|
41
37
|
```bash
|
|
42
38
|
npm install capacitor-pica-network-logger
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
39
|
npx cap sync
|
|
47
40
|
```
|
|
48
41
|
|
|
@@ -53,71 +46,86 @@ Add to your app's `capacitor.config.ts`:
|
|
|
53
46
|
```ts
|
|
54
47
|
plugins: {
|
|
55
48
|
PicaNetworkLogger: {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
redactJsonFields: ["password", "token"]
|
|
49
|
+
maxBodySize: 131072, // max chars per body (default: 128 KB)
|
|
50
|
+
notify: true, // show notifications per request (default: true)
|
|
51
|
+
redactHeaders: ["authorization", "cookie"], // header names to redact (default: none)
|
|
52
|
+
redactJsonFields: ["password", "token"] // JSON field names to redact (default: none)
|
|
61
53
|
}
|
|
62
54
|
}
|
|
63
55
|
```
|
|
64
56
|
|
|
57
|
+
| Option | Type | Default | Description |
|
|
58
|
+
|---|---|---|---|
|
|
59
|
+
| `maxBodySize` | `number` | `131072` | Maximum characters stored per request/response body. Truncated beyond this. |
|
|
60
|
+
| `notify` | `boolean` | `true` | Post a local notification for each completed request. On Android 13+ requests `POST_NOTIFICATIONS` permission. |
|
|
61
|
+
| `redactHeaders` | `string[]` | `[]` | Header names (case-insensitive) whose values are replaced with `[REDACTED]`. |
|
|
62
|
+
| `redactJsonFields` | `string[]` | `[]` | Top-level JSON body field names (case-insensitive) whose values are replaced with `[REDACTED]`. |
|
|
63
|
+
|
|
65
64
|
## Usage
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
The plugin exposes three methods: `startRequest`, `finishRequest`, and `openInspector`. Use your own HTTP client (e.g. `fetch`) and wrap calls with the logging methods:
|
|
68
67
|
|
|
69
68
|
```ts
|
|
70
|
-
import {
|
|
69
|
+
import { PicaNetworkLogger } from 'capacitor-pica-network-logger';
|
|
70
|
+
|
|
71
|
+
// 1. Log the start of a request
|
|
72
|
+
const { id } = await PicaNetworkLogger.startRequest({
|
|
73
|
+
method: 'GET',
|
|
74
|
+
url: 'https://jsonplaceholder.typicode.com/posts/1',
|
|
75
|
+
headers: { 'Accept': 'application/json' },
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// 2. Make the actual HTTP call
|
|
79
|
+
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
|
|
80
|
+
const body = await response.text();
|
|
81
|
+
|
|
82
|
+
// 3. Log the completion
|
|
83
|
+
await PicaNetworkLogger.finishRequest({
|
|
84
|
+
id,
|
|
85
|
+
status: response.status,
|
|
86
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
87
|
+
body,
|
|
88
|
+
});
|
|
71
89
|
|
|
72
|
-
|
|
90
|
+
// 4. Open the inspector UI
|
|
73
91
|
await PicaNetworkLogger.openInspector();
|
|
74
92
|
```
|
|
75
93
|
|
|
76
|
-
|
|
94
|
+
### API
|
|
77
95
|
|
|
78
|
-
|
|
96
|
+
| Method | Signature | Description |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| `startRequest` | `(options: StartRequestOptions) => Promise<{ id: string }>` | Log the start of a request. Returns an `id` for correlation. |
|
|
99
|
+
| `finishRequest` | `(options: FinishRequestOptions) => Promise<void>` | Log the completion of a request (status, headers, body, error). |
|
|
100
|
+
| `openInspector` | `() => Promise<void>` | Open the native inspector UI. |
|
|
79
101
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
**Vite**
|
|
102
|
+
### Types
|
|
83
103
|
|
|
84
104
|
```ts
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
'@capacitor/http': 'capacitor-pica-network-logger'
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
**Webpack**
|
|
105
|
+
interface StartRequestOptions {
|
|
106
|
+
method: string;
|
|
107
|
+
url: string;
|
|
108
|
+
headers?: Record<string, string>;
|
|
109
|
+
body?: unknown;
|
|
110
|
+
}
|
|
98
111
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
};
|
|
112
|
+
interface FinishRequestOptions {
|
|
113
|
+
id: string;
|
|
114
|
+
status?: number;
|
|
115
|
+
headers?: Record<string, string>;
|
|
116
|
+
body?: unknown;
|
|
117
|
+
error?: string;
|
|
118
|
+
}
|
|
108
119
|
```
|
|
109
120
|
|
|
110
|
-
|
|
121
|
+
## Project layout
|
|
111
122
|
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
123
|
+
```
|
|
124
|
+
src/ TypeScript plugin registration and types
|
|
125
|
+
ios/Plugin/ Swift iOS plugin (UIKit inspector, SQLite storage, notifications)
|
|
126
|
+
android/ Kotlin Android plugin (Compose inspector, SQLite storage, notifications)
|
|
127
|
+
examples/ Sample Capacitor app for manual testing
|
|
128
|
+
scripts/ Release script
|
|
121
129
|
```
|
|
122
130
|
|
|
123
131
|
## Build
|
|
@@ -137,15 +145,26 @@ npm install
|
|
|
137
145
|
npm run dev
|
|
138
146
|
```
|
|
139
147
|
|
|
140
|
-
|
|
148
|
+
Run on device:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# iOS
|
|
152
|
+
cd examples/sample-app && npm run build && npx cap sync ios && npx cap run ios
|
|
153
|
+
|
|
154
|
+
# Android
|
|
155
|
+
cd examples/sample-app && npm run build && npx cap sync android && npx cap run android
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Release
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npm run release # prompts for patch/minor/major
|
|
162
|
+
npm run release -- patch # patch bump
|
|
163
|
+
npm run release -- 1.0.0 # explicit version
|
|
164
|
+
```
|
|
141
165
|
|
|
142
|
-
|
|
143
|
-
- Android hook: `android/src/main/java/com/linakis/capacitorpicanetworklogger/ReflectionHook.kt`
|
|
144
|
-
- iOS logger: `ios/Plugin/InspectorURLProtocol.swift`
|
|
145
|
-
- UI (iOS): `ios/Plugin/InspectorViewController.swift`
|
|
146
|
-
- UI (Android): `android/src/main/java/com/linakis/capacitorpicanetworklogger/InspectorActivity.kt`
|
|
166
|
+
The release script updates `CHANGELOG.md`, bumps `package.json`, builds, commits, tags, pushes, publishes to npm, and creates a GitHub Release (if `gh` CLI is available).
|
|
147
167
|
|
|
148
|
-
##
|
|
168
|
+
## License
|
|
149
169
|
|
|
150
|
-
|
|
151
|
-
- The JS wrapper is still authoritative on Android; reflection logging is best-effort.
|
|
170
|
+
MIT
|
|
@@ -6,8 +6,8 @@ object LogRepositoryStore {
|
|
|
6
6
|
private var repository: LogRepository? = null
|
|
7
7
|
private var appContext: android.content.Context? = null
|
|
8
8
|
private var maxBodySize: Int = 131072
|
|
9
|
-
private var redactHeaders: Set<String> =
|
|
10
|
-
private var redactJsonFields: Set<String> =
|
|
9
|
+
private var redactHeaders: Set<String> = emptySet()
|
|
10
|
+
private var redactJsonFields: Set<String> = emptySet()
|
|
11
11
|
private var notifyEnabled: Boolean = true
|
|
12
12
|
private val requestStartTs: MutableMap<String, Long> = mutableMapOf()
|
|
13
13
|
|
|
@@ -78,9 +78,15 @@ object LogRepositoryStore {
|
|
|
78
78
|
data.put("id", id)
|
|
79
79
|
if (status != null) data.put("status", status)
|
|
80
80
|
data.put("headers", headers?.redactedHeaders()?.toJsObject())
|
|
81
|
-
val
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
val contentType = contentType(headers)
|
|
82
|
+
if (body != null && isBinaryContentType(contentType)) {
|
|
83
|
+
data.put("responseBody", binaryPlaceholder(contentType))
|
|
84
|
+
data.put("responseBodyTruncated", false)
|
|
85
|
+
} else {
|
|
86
|
+
val truncated = truncate(body?.redactJson())
|
|
87
|
+
data.put("responseBody", truncated.value)
|
|
88
|
+
data.put("responseBodyTruncated", truncated.truncated)
|
|
89
|
+
}
|
|
84
90
|
if (error != null) data.put("error", error)
|
|
85
91
|
if (protocol != null) data.put("protocol", protocol)
|
|
86
92
|
if (ssl != null) data.put("ssl", ssl)
|
|
@@ -121,6 +127,36 @@ object LogRepositoryStore {
|
|
|
121
127
|
}
|
|
122
128
|
|
|
123
129
|
private data class Truncated(val value: String?, val truncated: Boolean)
|
|
130
|
+
|
|
131
|
+
private fun contentType(headers: Map<String, String>?): String? {
|
|
132
|
+
if (headers == null) return null
|
|
133
|
+
for ((key, value) in headers) {
|
|
134
|
+
if (key.lowercase() == "content-type") return value.lowercase()
|
|
135
|
+
}
|
|
136
|
+
return null
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private val binaryPrefixes = listOf(
|
|
140
|
+
"image/", "video/", "audio/", "application/octet-stream",
|
|
141
|
+
"application/pdf", "application/zip", "application/gzip",
|
|
142
|
+
"font/", "application/vnd.", "application/x-protobuf"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
private fun isBinaryContentType(contentType: String?): Boolean {
|
|
146
|
+
val ct = contentType ?: return false
|
|
147
|
+
return binaryPrefixes.any { ct.startsWith(it) }
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private fun binaryPlaceholder(contentType: String?): String {
|
|
151
|
+
val ct = contentType ?: "unknown"
|
|
152
|
+
val mediaType = when {
|
|
153
|
+
ct.startsWith("image/") -> "Image"
|
|
154
|
+
ct.startsWith("video/") -> "Video"
|
|
155
|
+
ct.startsWith("audio/") -> "Audio"
|
|
156
|
+
else -> "Binary"
|
|
157
|
+
}
|
|
158
|
+
return "[$mediaType preview not yet supported ($ct)]"
|
|
159
|
+
}
|
|
124
160
|
}
|
|
125
161
|
|
|
126
162
|
private fun Map<String, String>.toJsObject(): JSObject {
|
package/android/src/main/java/com/linakis/capacitorpicanetworklogger/LoggerConfigProvider.kt
CHANGED
|
@@ -7,6 +7,7 @@ class LoggerConfigProvider {
|
|
|
7
7
|
fun getConfig(plugin: Plugin): JSObject {
|
|
8
8
|
val config = plugin.bridge.config.getPluginConfiguration("PicaNetworkLogger")
|
|
9
9
|
val output = JSObject()
|
|
10
|
+
output.put("enabled", config.getBoolean("enabled", true))
|
|
10
11
|
output.put("maxBodySize", config.getInt("maxBodySize", 131072))
|
|
11
12
|
output.put("redactHeaders", config.getArray("redactHeaders"))
|
|
12
13
|
output.put("redactJsonFields", config.getArray("redactJsonFields"))
|
package/android/src/main/java/com/linakis/capacitorpicanetworklogger/PicaNetworkLoggerPlugin.kt
CHANGED
|
@@ -14,11 +14,14 @@ import org.json.JSONObject
|
|
|
14
14
|
class PicaNetworkLoggerPlugin : Plugin() {
|
|
15
15
|
private val repository = LogRepository()
|
|
16
16
|
private val configProvider = LoggerConfigProvider()
|
|
17
|
+
private var enabled = true
|
|
17
18
|
|
|
18
19
|
override fun load() {
|
|
19
20
|
super.load()
|
|
20
|
-
repository.attach(bridge.context)
|
|
21
21
|
val config = configProvider.getConfig(this)
|
|
22
|
+
enabled = config.optBoolean("enabled", true)
|
|
23
|
+
if (!enabled) return
|
|
24
|
+
repository.attach(bridge.context)
|
|
22
25
|
LogRepositoryStore.attach(bridge.context, repository, config.getInt("maxBodySize"))
|
|
23
26
|
val redactHeaders = config.get("redactHeaders")?.let { value ->
|
|
24
27
|
when (value) {
|
|
@@ -54,6 +57,12 @@ class PicaNetworkLoggerPlugin : Plugin() {
|
|
|
54
57
|
|
|
55
58
|
@PluginMethod
|
|
56
59
|
fun startRequest(call: PluginCall) {
|
|
60
|
+
if (!enabled) {
|
|
61
|
+
val ret = JSObject()
|
|
62
|
+
ret.put("id", "")
|
|
63
|
+
call.resolve(ret)
|
|
64
|
+
return
|
|
65
|
+
}
|
|
57
66
|
val method = call.getString("method") ?: "GET"
|
|
58
67
|
val url = call.getString("url") ?: ""
|
|
59
68
|
val headers = call.getObject("headers")?.let { obj ->
|
|
@@ -69,6 +78,10 @@ class PicaNetworkLoggerPlugin : Plugin() {
|
|
|
69
78
|
|
|
70
79
|
@PluginMethod
|
|
71
80
|
fun finishRequest(call: PluginCall) {
|
|
81
|
+
if (!enabled) {
|
|
82
|
+
call.resolve()
|
|
83
|
+
return
|
|
84
|
+
}
|
|
72
85
|
val id = call.getString("id") ?: return call.reject("Missing id")
|
|
73
86
|
val status = call.getInt("status")
|
|
74
87
|
val headers = call.getObject("headers")?.let { obj ->
|
|
@@ -82,6 +95,10 @@ class PicaNetworkLoggerPlugin : Plugin() {
|
|
|
82
95
|
|
|
83
96
|
@PluginMethod
|
|
84
97
|
fun openInspector(call: PluginCall) {
|
|
98
|
+
if (!enabled) {
|
|
99
|
+
call.resolve()
|
|
100
|
+
return
|
|
101
|
+
}
|
|
85
102
|
val context = bridge.context
|
|
86
103
|
val intent = android.content.Intent(context, InspectorActivity::class.java)
|
|
87
104
|
intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
@@ -4,8 +4,8 @@ class InspectorLogger {
|
|
|
4
4
|
static let shared = InspectorLogger()
|
|
5
5
|
private let repository = LogRepository.shared
|
|
6
6
|
private var maxBodySize: Int = 131072
|
|
7
|
-
private var redactHeaders: Set<String> = [
|
|
8
|
-
private var redactJsonFields: Set<String> = [
|
|
7
|
+
private var redactHeaders: Set<String> = []
|
|
8
|
+
private var redactJsonFields: Set<String> = []
|
|
9
9
|
private var notifyEnabled: Bool = true
|
|
10
10
|
private var requestMethods: [String: String] = [:]
|
|
11
11
|
private var requestUrls: [String: String] = [:]
|
|
@@ -64,9 +64,15 @@ class InspectorLogger {
|
|
|
64
64
|
payload["headers"] = redact(headers)
|
|
65
65
|
}
|
|
66
66
|
if let body = body {
|
|
67
|
-
let
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
let contentType = contentType(from: headers)
|
|
68
|
+
if isBinaryContentType(contentType) {
|
|
69
|
+
payload["responseBody"] = binaryPlaceholder(contentType)
|
|
70
|
+
payload["responseBodyTruncated"] = false
|
|
71
|
+
} else {
|
|
72
|
+
let truncated = truncate(redactJson(body))
|
|
73
|
+
payload["responseBody"] = truncated.value
|
|
74
|
+
payload["responseBodyTruncated"] = truncated.truncated
|
|
75
|
+
}
|
|
70
76
|
}
|
|
71
77
|
if let error = error {
|
|
72
78
|
payload["error"] = error
|
|
@@ -154,4 +160,37 @@ class InspectorLogger {
|
|
|
154
160
|
func setNotify(enabled: Bool) {
|
|
155
161
|
notifyEnabled = enabled
|
|
156
162
|
}
|
|
163
|
+
|
|
164
|
+
private func contentType(from headers: [String: Any]?) -> String? {
|
|
165
|
+
guard let headers = headers else { return nil }
|
|
166
|
+
for (key, value) in headers {
|
|
167
|
+
if key.lowercased() == "content-type", let str = value as? String {
|
|
168
|
+
return str.lowercased()
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return nil
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private func isBinaryContentType(_ contentType: String?) -> Bool {
|
|
175
|
+
guard let ct = contentType else { return false }
|
|
176
|
+
let binaryPrefixes = ["image/", "video/", "audio/", "application/octet-stream",
|
|
177
|
+
"application/pdf", "application/zip", "application/gzip",
|
|
178
|
+
"font/", "application/vnd.", "application/x-protobuf"]
|
|
179
|
+
return binaryPrefixes.contains { ct.hasPrefix($0) }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private func binaryPlaceholder(_ contentType: String?) -> String {
|
|
183
|
+
let ct = contentType ?? "unknown"
|
|
184
|
+
let mediaType: String
|
|
185
|
+
if ct.hasPrefix("image/") {
|
|
186
|
+
mediaType = "Image"
|
|
187
|
+
} else if ct.hasPrefix("video/") {
|
|
188
|
+
mediaType = "Video"
|
|
189
|
+
} else if ct.hasPrefix("audio/") {
|
|
190
|
+
mediaType = "Audio"
|
|
191
|
+
} else {
|
|
192
|
+
mediaType = "Binary"
|
|
193
|
+
}
|
|
194
|
+
return "[\(mediaType) preview not yet supported (\(ct))]"
|
|
195
|
+
}
|
|
157
196
|
}
|
|
@@ -14,8 +14,13 @@ public class PicaNetworkLoggerPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
14
14
|
CAPPluginMethod(name: "openInspector", returnType: CAPPluginReturnPromise)
|
|
15
15
|
]
|
|
16
16
|
private let configProvider = LoggerConfigProvider()
|
|
17
|
+
private var enabled = true
|
|
17
18
|
|
|
18
19
|
@objc func startRequest(_ call: CAPPluginCall) {
|
|
20
|
+
guard enabled else {
|
|
21
|
+
call.resolve(["id": ""])
|
|
22
|
+
return
|
|
23
|
+
}
|
|
19
24
|
let id = UUID().uuidString
|
|
20
25
|
let method = call.getString("method") ?? "GET"
|
|
21
26
|
let url = call.getString("url") ?? ""
|
|
@@ -32,6 +37,10 @@ public class PicaNetworkLoggerPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
@objc func finishRequest(_ call: CAPPluginCall) {
|
|
40
|
+
guard enabled else {
|
|
41
|
+
call.resolve()
|
|
42
|
+
return
|
|
43
|
+
}
|
|
35
44
|
guard let id = call.getString("id") else {
|
|
36
45
|
call.reject("Missing id")
|
|
37
46
|
return
|
|
@@ -55,6 +64,8 @@ public class PicaNetworkLoggerPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
55
64
|
public override func load() {
|
|
56
65
|
super.load()
|
|
57
66
|
let config = configProvider.getConfig(self)
|
|
67
|
+
enabled = config["enabled"] as? Bool ?? true
|
|
68
|
+
guard enabled else { return }
|
|
58
69
|
if let size = config["maxBodySize"] as? Int {
|
|
59
70
|
InspectorLogger.shared.setMaxBodySize(size)
|
|
60
71
|
}
|
|
@@ -74,6 +85,10 @@ public class PicaNetworkLoggerPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
74
85
|
}
|
|
75
86
|
|
|
76
87
|
@objc func openInspector(_ call: CAPPluginCall) {
|
|
88
|
+
guard enabled else {
|
|
89
|
+
call.resolve()
|
|
90
|
+
return
|
|
91
|
+
}
|
|
77
92
|
#if canImport(UIKit)
|
|
78
93
|
DispatchQueue.main.async { [weak self] in
|
|
79
94
|
let inspector = UINavigationController(rootViewController: InspectorViewController())
|