@hot-updater/plugin-insights 1.0.0-rc.27 → 1.0.0-rc.28
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/dist/client/errorDetails.cjs +34 -0
- package/dist/client/errorDetails.mjs +34 -0
- package/dist/client/index.cjs +7 -3
- package/dist/client/index.mjs +7 -3
- package/dist/server/domain.d.cts +5 -0
- package/dist/server/domain.d.mts +5 -0
- package/dist/server/eventInput.cjs +6 -0
- package/dist/server/eventInput.mjs +6 -0
- package/dist/server/eventRow.cjs +1 -1
- package/dist/server/eventRow.d.cts +2 -0
- package/dist/server/eventRow.d.mts +2 -0
- package/dist/server/eventRow.mjs +1 -1
- package/dist/server/provider.cjs +4 -0
- package/dist/server/provider.mjs +4 -0
- package/package.json +1 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
let _hot_updater_protocol = require("@hot-updater/protocol");
|
|
2
|
+
//#region src/client/errorDetails.ts
|
|
3
|
+
/** Bound the JSON wire size without rewriting the error text or splitting Unicode. */
|
|
4
|
+
const boundedText = (text, maxBytes) => {
|
|
5
|
+
if ((0, _hot_updater_protocol.getUtf8ByteLength)(JSON.stringify(text)) <= maxBytes) return text;
|
|
6
|
+
let result = "";
|
|
7
|
+
let bytes = 2 + (0, _hot_updater_protocol.getUtf8ByteLength)("…");
|
|
8
|
+
for (const character of text) {
|
|
9
|
+
bytes += (0, _hot_updater_protocol.getUtf8ByteLength)(JSON.stringify(character)) - 2;
|
|
10
|
+
if (bytes > maxBytes) break;
|
|
11
|
+
result += character;
|
|
12
|
+
}
|
|
13
|
+
return `${result}…`;
|
|
14
|
+
};
|
|
15
|
+
/** Error properties are not enumerable, so JSON.stringify(error) would lose them. */
|
|
16
|
+
const readErrorDetails = (error) => {
|
|
17
|
+
if (error == null) return {};
|
|
18
|
+
const object = typeof error === "object" ? error : null;
|
|
19
|
+
let message;
|
|
20
|
+
if (object && "message" in object && typeof object.message === "string") message = object.message;
|
|
21
|
+
else if (typeof error === "string") message = error;
|
|
22
|
+
else try {
|
|
23
|
+
message = JSON.stringify(error) ?? String(error);
|
|
24
|
+
} catch {
|
|
25
|
+
message = String(error);
|
|
26
|
+
}
|
|
27
|
+
const stack = object && "stack" in object && typeof object.stack === "string" ? object.stack : void 0;
|
|
28
|
+
return {
|
|
29
|
+
...message ? { errorMessage: boundedText(message, 2048) } : {},
|
|
30
|
+
...stack ? { errorStack: boundedText(stack, 4096) } : {}
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
//#endregion
|
|
34
|
+
exports.readErrorDetails = readErrorDetails;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { getUtf8ByteLength } from "@hot-updater/protocol";
|
|
2
|
+
//#region src/client/errorDetails.ts
|
|
3
|
+
/** Bound the JSON wire size without rewriting the error text or splitting Unicode. */
|
|
4
|
+
const boundedText = (text, maxBytes) => {
|
|
5
|
+
if (getUtf8ByteLength(JSON.stringify(text)) <= maxBytes) return text;
|
|
6
|
+
let result = "";
|
|
7
|
+
let bytes = 2 + getUtf8ByteLength("…");
|
|
8
|
+
for (const character of text) {
|
|
9
|
+
bytes += getUtf8ByteLength(JSON.stringify(character)) - 2;
|
|
10
|
+
if (bytes > maxBytes) break;
|
|
11
|
+
result += character;
|
|
12
|
+
}
|
|
13
|
+
return `${result}…`;
|
|
14
|
+
};
|
|
15
|
+
/** Error properties are not enumerable, so JSON.stringify(error) would lose them. */
|
|
16
|
+
const readErrorDetails = (error) => {
|
|
17
|
+
if (error == null) return {};
|
|
18
|
+
const object = typeof error === "object" ? error : null;
|
|
19
|
+
let message;
|
|
20
|
+
if (object && "message" in object && typeof object.message === "string") message = object.message;
|
|
21
|
+
else if (typeof error === "string") message = error;
|
|
22
|
+
else try {
|
|
23
|
+
message = JSON.stringify(error) ?? String(error);
|
|
24
|
+
} catch {
|
|
25
|
+
message = String(error);
|
|
26
|
+
}
|
|
27
|
+
const stack = object && "stack" in object && typeof object.stack === "string" ? object.stack : void 0;
|
|
28
|
+
return {
|
|
29
|
+
...message ? { errorMessage: boundedText(message, 2048) } : {},
|
|
30
|
+
...stack ? { errorStack: boundedText(stack, 4096) } : {}
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
//#endregion
|
|
34
|
+
export { readErrorDetails };
|
package/dist/client/index.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_errorDetails = require("./errorDetails.cjs");
|
|
2
3
|
const require_eventId = require("./eventId.cjs");
|
|
3
4
|
const require_sender = require("./sender.cjs");
|
|
4
5
|
const require_state = require("./state.cjs");
|
|
@@ -140,11 +141,13 @@ const insights = (options = {}) => {
|
|
|
140
141
|
const onUpdateError = (error) => {
|
|
141
142
|
if (error.stage === "check" && error.reason === "network") return;
|
|
142
143
|
const targetBundleId = error.targetBundleId ?? error.bundleId;
|
|
143
|
-
const
|
|
144
|
+
const details = require_errorDetails.readErrorDetails(error.cause);
|
|
145
|
+
const failureKey = JSON.stringify([
|
|
144
146
|
error.stage,
|
|
145
147
|
error.reason,
|
|
146
|
-
targetBundleId
|
|
147
|
-
|
|
148
|
+
targetBundleId,
|
|
149
|
+
details.errorMessage ?? null
|
|
150
|
+
]);
|
|
148
151
|
const event = createEvent({
|
|
149
152
|
type: "UPDATE_FAILED",
|
|
150
153
|
channel: error.channel,
|
|
@@ -156,6 +159,7 @@ const insights = (options = {}) => {
|
|
|
156
159
|
metadata: { failure: {
|
|
157
160
|
stage: error.stage,
|
|
158
161
|
reason: error.reason,
|
|
162
|
+
...details,
|
|
159
163
|
...error.resource === void 0 ? {} : { resource: error.resource },
|
|
160
164
|
...error.httpStatus === void 0 ? {} : { httpStatus: error.httpStatus },
|
|
161
165
|
...error.transport === void 0 ? {} : { transport: error.transport },
|
package/dist/client/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readErrorDetails } from "./errorDetails.mjs";
|
|
1
2
|
import { createKeyedUUIDv7, createUUIDv7 } from "./eventId.mjs";
|
|
2
3
|
import { createInsightsEventSender } from "./sender.mjs";
|
|
3
4
|
import { createInsightsState, utcDay, utcDayStart } from "./state.mjs";
|
|
@@ -139,11 +140,13 @@ const insights = (options = {}) => {
|
|
|
139
140
|
const onUpdateError = (error) => {
|
|
140
141
|
if (error.stage === "check" && error.reason === "network") return;
|
|
141
142
|
const targetBundleId = error.targetBundleId ?? error.bundleId;
|
|
142
|
-
const
|
|
143
|
+
const details = readErrorDetails(error.cause);
|
|
144
|
+
const failureKey = JSON.stringify([
|
|
143
145
|
error.stage,
|
|
144
146
|
error.reason,
|
|
145
|
-
targetBundleId
|
|
146
|
-
|
|
147
|
+
targetBundleId,
|
|
148
|
+
details.errorMessage ?? null
|
|
149
|
+
]);
|
|
147
150
|
const event = createEvent({
|
|
148
151
|
type: "UPDATE_FAILED",
|
|
149
152
|
channel: error.channel,
|
|
@@ -155,6 +158,7 @@ const insights = (options = {}) => {
|
|
|
155
158
|
metadata: { failure: {
|
|
156
159
|
stage: error.stage,
|
|
157
160
|
reason: error.reason,
|
|
161
|
+
...details,
|
|
158
162
|
...error.resource === void 0 ? {} : { resource: error.resource },
|
|
159
163
|
...error.httpStatus === void 0 ? {} : { httpStatus: error.httpStatus },
|
|
160
164
|
...error.transport === void 0 ? {} : { transport: error.transport },
|
package/dist/server/domain.d.cts
CHANGED
|
@@ -14,6 +14,9 @@ type BundleEventFailureInput = {
|
|
|
14
14
|
readonly transport?: NonNullable<BundleEventFailure["transport"]>;
|
|
15
15
|
/** The storage origin's error code, such as `ExpiredToken`. */
|
|
16
16
|
readonly originCode?: string;
|
|
17
|
+
/** Original client error text, bounded to fit the event payload. */
|
|
18
|
+
readonly errorMessage?: string;
|
|
19
|
+
readonly errorStack?: string;
|
|
17
20
|
/** Android's `ApplicationExitInfo` reason for the process before this one. */
|
|
18
21
|
readonly previousProcessExit?: string;
|
|
19
22
|
};
|
|
@@ -78,6 +81,8 @@ type CreateBundleEventRequest = (Movement & {
|
|
|
78
81
|
});
|
|
79
82
|
type ActiveInstallationWindow = "24h" | "7d" | "30d";
|
|
80
83
|
type EventHistoryRow = {
|
|
84
|
+
readonly toReleaseId?: string;
|
|
85
|
+
readonly sdkVersion?: string;
|
|
81
86
|
readonly id: string;
|
|
82
87
|
readonly installId: string;
|
|
83
88
|
readonly type: "UPDATE_DOWNLOADED" | "UPDATE_APPLIED" | "RECOVERED" | "UPDATE_FAILED" | "UNCHANGED";
|
package/dist/server/domain.d.mts
CHANGED
|
@@ -14,6 +14,9 @@ type BundleEventFailureInput = {
|
|
|
14
14
|
readonly transport?: NonNullable<BundleEventFailure["transport"]>;
|
|
15
15
|
/** The storage origin's error code, such as `ExpiredToken`. */
|
|
16
16
|
readonly originCode?: string;
|
|
17
|
+
/** Original client error text, bounded to fit the event payload. */
|
|
18
|
+
readonly errorMessage?: string;
|
|
19
|
+
readonly errorStack?: string;
|
|
17
20
|
/** Android's `ApplicationExitInfo` reason for the process before this one. */
|
|
18
21
|
readonly previousProcessExit?: string;
|
|
19
22
|
};
|
|
@@ -78,6 +81,8 @@ type CreateBundleEventRequest = (Movement & {
|
|
|
78
81
|
});
|
|
79
82
|
type ActiveInstallationWindow = "24h" | "7d" | "30d";
|
|
80
83
|
type EventHistoryRow = {
|
|
84
|
+
readonly toReleaseId?: string;
|
|
85
|
+
readonly sdkVersion?: string;
|
|
81
86
|
readonly id: string;
|
|
82
87
|
readonly installId: string;
|
|
83
88
|
readonly type: "UPDATE_DOWNLOADED" | "UPDATE_APPLIED" | "RECOVERED" | "UPDATE_FAILED" | "UNCHANGED";
|
|
@@ -83,6 +83,8 @@ function readFailure(value) {
|
|
|
83
83
|
const failure = isRecord(value) ? value : {};
|
|
84
84
|
const httpStatus = failure.httpStatus;
|
|
85
85
|
const originCode = readCode(failure.originCode);
|
|
86
|
+
const errorMessage = typeof failure.errorMessage === "string" && failure.errorMessage.length <= 2048 ? failure.errorMessage : void 0;
|
|
87
|
+
const errorStack = typeof failure.errorStack === "string" && failure.errorStack.length <= 4096 ? failure.errorStack : void 0;
|
|
86
88
|
const previousProcessExit = readCode(failure.previousProcessExit);
|
|
87
89
|
return {
|
|
88
90
|
stage: oneOf(STAGES, failure.stage),
|
|
@@ -91,6 +93,8 @@ function readFailure(value) {
|
|
|
91
93
|
...Number.isSafeInteger(httpStatus) && httpStatus >= 100 && httpStatus <= 599 ? { httpStatus } : {},
|
|
92
94
|
...failure.transport == null ? {} : { transport: oneOf(TRANSPORTS, failure.transport) },
|
|
93
95
|
...originCode === void 0 ? {} : { originCode },
|
|
96
|
+
...errorMessage === void 0 ? {} : { errorMessage },
|
|
97
|
+
...errorStack === void 0 ? {} : { errorStack },
|
|
94
98
|
...previousProcessExit === void 0 ? {} : { previousProcessExit }
|
|
95
99
|
};
|
|
96
100
|
}
|
|
@@ -261,6 +265,8 @@ function createBundleEventRow(input) {
|
|
|
261
265
|
failure: {
|
|
262
266
|
stage: failure.stage,
|
|
263
267
|
reason: failure.reason,
|
|
268
|
+
...failure.errorMessage === void 0 ? {} : { error_message: failure.errorMessage },
|
|
269
|
+
...failure.errorStack === void 0 ? {} : { error_stack: failure.errorStack },
|
|
264
270
|
...failure.resource === void 0 ? {} : { resource: failure.resource },
|
|
265
271
|
...failure.httpStatus === void 0 ? {} : { http_status: failure.httpStatus },
|
|
266
272
|
...failure.transport === void 0 ? {} : { transport: failure.transport },
|
|
@@ -83,6 +83,8 @@ function readFailure(value) {
|
|
|
83
83
|
const failure = isRecord(value) ? value : {};
|
|
84
84
|
const httpStatus = failure.httpStatus;
|
|
85
85
|
const originCode = readCode(failure.originCode);
|
|
86
|
+
const errorMessage = typeof failure.errorMessage === "string" && failure.errorMessage.length <= 2048 ? failure.errorMessage : void 0;
|
|
87
|
+
const errorStack = typeof failure.errorStack === "string" && failure.errorStack.length <= 4096 ? failure.errorStack : void 0;
|
|
86
88
|
const previousProcessExit = readCode(failure.previousProcessExit);
|
|
87
89
|
return {
|
|
88
90
|
stage: oneOf(STAGES, failure.stage),
|
|
@@ -91,6 +93,8 @@ function readFailure(value) {
|
|
|
91
93
|
...Number.isSafeInteger(httpStatus) && httpStatus >= 100 && httpStatus <= 599 ? { httpStatus } : {},
|
|
92
94
|
...failure.transport == null ? {} : { transport: oneOf(TRANSPORTS, failure.transport) },
|
|
93
95
|
...originCode === void 0 ? {} : { originCode },
|
|
96
|
+
...errorMessage === void 0 ? {} : { errorMessage },
|
|
97
|
+
...errorStack === void 0 ? {} : { errorStack },
|
|
94
98
|
...previousProcessExit === void 0 ? {} : { previousProcessExit }
|
|
95
99
|
};
|
|
96
100
|
}
|
|
@@ -261,6 +265,8 @@ function createBundleEventRow(input) {
|
|
|
261
265
|
failure: {
|
|
262
266
|
stage: failure.stage,
|
|
263
267
|
reason: failure.reason,
|
|
268
|
+
...failure.errorMessage === void 0 ? {} : { error_message: failure.errorMessage },
|
|
269
|
+
...failure.errorStack === void 0 ? {} : { error_stack: failure.errorStack },
|
|
264
270
|
...failure.resource === void 0 ? {} : { resource: failure.resource },
|
|
265
271
|
...failure.httpStatus === void 0 ? {} : { http_status: failure.httpStatus },
|
|
266
272
|
...failure.transport === void 0 ? {} : { transport: failure.transport },
|
package/dist/server/eventRow.cjs
CHANGED
|
@@ -3,7 +3,7 @@ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
|
3
3
|
const isOptional = (value, key, valid) => !Object.hasOwn(value, key) || valid(value[key]);
|
|
4
4
|
const isString = (value) => typeof value === "string";
|
|
5
5
|
/** An `UPDATE_FAILED` report's stored failure: a stage and a reason, and what else the client knew. */
|
|
6
|
-
const isDatabaseBundleEventFailure = (value) => (0, _hot_updater_plugin_core.isDatabaseJsonObject)(value) && isString(value.stage) && isString(value.reason) && isOptional(value, "resource", isString) && isOptional(value, "http_status", (status) => Number.isSafeInteger(status)) && isOptional(value, "transport", isString) && isOptional(value, "origin_code", isString) && isOptional(value, "previous_process_exit", isString);
|
|
6
|
+
const isDatabaseBundleEventFailure = (value) => (0, _hot_updater_plugin_core.isDatabaseJsonObject)(value) && isString(value.stage) && isString(value.reason) && isOptional(value, "resource", isString) && isOptional(value, "http_status", (status) => Number.isSafeInteger(status)) && isOptional(value, "transport", isString) && isOptional(value, "origin_code", isString) && isOptional(value, "error_message", isString) && isOptional(value, "error_stack", isString) && isOptional(value, "previous_process_exit", isString);
|
|
7
7
|
const isDatabaseBundleEventMetadata = (value) => (0, _hot_updater_plugin_core.isDatabaseJsonObject)(value) && typeof value.cohort === "string" && (value.update_strategy === null || value.update_strategy === "fingerprint" || value.update_strategy === "appVersion") && (value.fingerprint_hash === null || typeof value.fingerprint_hash === "string") && (value.sdk_version === null || typeof value.sdk_version === "string") && isOptional(value, "failure", isDatabaseBundleEventFailure) && isOptional(value, "delivery", isString) && isOptional(value, "patch_fallback", (flag) => typeof flag === "boolean") && isOptional(value, "previous_process_exit", isString);
|
|
8
8
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
9
|
const isIdentity = (value) => typeof value === "string" && value.length > 0 && value.length <= 255;
|
|
@@ -14,6 +14,8 @@ type BundleEventFailure = DatabaseJsonObject & {
|
|
|
14
14
|
readonly transport?: "timeout" | "dns" | "tls" | "connection" | "offline" | "cancelled" | "unknown";
|
|
15
15
|
/** The storage origin's error code, such as `ExpiredToken`. */
|
|
16
16
|
readonly origin_code?: string;
|
|
17
|
+
readonly error_message?: string;
|
|
18
|
+
readonly error_stack?: string;
|
|
17
19
|
/** Android's `ApplicationExitInfo` reason for the process before this one. */
|
|
18
20
|
readonly previous_process_exit?: string;
|
|
19
21
|
};
|
|
@@ -14,6 +14,8 @@ type BundleEventFailure = DatabaseJsonObject & {
|
|
|
14
14
|
readonly transport?: "timeout" | "dns" | "tls" | "connection" | "offline" | "cancelled" | "unknown";
|
|
15
15
|
/** The storage origin's error code, such as `ExpiredToken`. */
|
|
16
16
|
readonly origin_code?: string;
|
|
17
|
+
readonly error_message?: string;
|
|
18
|
+
readonly error_stack?: string;
|
|
17
19
|
/** Android's `ApplicationExitInfo` reason for the process before this one. */
|
|
18
20
|
readonly previous_process_exit?: string;
|
|
19
21
|
};
|
package/dist/server/eventRow.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { DatabaseAdapterInputError, isDatabaseJsonObject } from "@hot-updater/pl
|
|
|
3
3
|
const isOptional = (value, key, valid) => !Object.hasOwn(value, key) || valid(value[key]);
|
|
4
4
|
const isString = (value) => typeof value === "string";
|
|
5
5
|
/** An `UPDATE_FAILED` report's stored failure: a stage and a reason, and what else the client knew. */
|
|
6
|
-
const isDatabaseBundleEventFailure = (value) => isDatabaseJsonObject(value) && isString(value.stage) && isString(value.reason) && isOptional(value, "resource", isString) && isOptional(value, "http_status", (status) => Number.isSafeInteger(status)) && isOptional(value, "transport", isString) && isOptional(value, "origin_code", isString) && isOptional(value, "previous_process_exit", isString);
|
|
6
|
+
const isDatabaseBundleEventFailure = (value) => isDatabaseJsonObject(value) && isString(value.stage) && isString(value.reason) && isOptional(value, "resource", isString) && isOptional(value, "http_status", (status) => Number.isSafeInteger(status)) && isOptional(value, "transport", isString) && isOptional(value, "origin_code", isString) && isOptional(value, "error_message", isString) && isOptional(value, "error_stack", isString) && isOptional(value, "previous_process_exit", isString);
|
|
7
7
|
const isDatabaseBundleEventMetadata = (value) => isDatabaseJsonObject(value) && typeof value.cohort === "string" && (value.update_strategy === null || value.update_strategy === "fingerprint" || value.update_strategy === "appVersion") && (value.fingerprint_hash === null || typeof value.fingerprint_hash === "string") && (value.sdk_version === null || typeof value.sdk_version === "string") && isOptional(value, "failure", isDatabaseBundleEventFailure) && isOptional(value, "delivery", isString) && isOptional(value, "patch_fallback", (flag) => typeof flag === "boolean") && isOptional(value, "previous_process_exit", isString);
|
|
8
8
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
9
|
const isIdentity = (value) => typeof value === "string" && value.length > 0 && value.length <= 255;
|
package/dist/server/provider.cjs
CHANGED
|
@@ -147,6 +147,8 @@ const assertEventRows = (rows, input) => {
|
|
|
147
147
|
const toFailure = (failure) => ({
|
|
148
148
|
stage: failure.stage,
|
|
149
149
|
reason: failure.reason,
|
|
150
|
+
...failure.error_message === void 0 ? {} : { errorMessage: failure.error_message },
|
|
151
|
+
...failure.error_stack === void 0 ? {} : { errorStack: failure.error_stack },
|
|
150
152
|
...failure.resource === void 0 ? {} : { resource: failure.resource },
|
|
151
153
|
...failure.http_status === void 0 ? {} : { httpStatus: failure.http_status },
|
|
152
154
|
...failure.transport === void 0 ? {} : { transport: failure.transport },
|
|
@@ -161,6 +163,8 @@ const eventDetails = ({ type, metadata }) => ({
|
|
|
161
163
|
...type === "RECOVERED" && metadata.previous_process_exit !== void 0 ? { previousProcessExit: metadata.previous_process_exit } : {}
|
|
162
164
|
});
|
|
163
165
|
const toEventHistoryRow = (row) => ({
|
|
166
|
+
...row.to_release_id == null ? {} : { toReleaseId: row.to_release_id },
|
|
167
|
+
...row.metadata.sdk_version == null ? {} : { sdkVersion: row.metadata.sdk_version },
|
|
164
168
|
appVersion: row.app_version,
|
|
165
169
|
channel: row.channel,
|
|
166
170
|
cohort: row.metadata.cohort,
|
package/dist/server/provider.mjs
CHANGED
|
@@ -147,6 +147,8 @@ const assertEventRows = (rows, input) => {
|
|
|
147
147
|
const toFailure = (failure) => ({
|
|
148
148
|
stage: failure.stage,
|
|
149
149
|
reason: failure.reason,
|
|
150
|
+
...failure.error_message === void 0 ? {} : { errorMessage: failure.error_message },
|
|
151
|
+
...failure.error_stack === void 0 ? {} : { errorStack: failure.error_stack },
|
|
150
152
|
...failure.resource === void 0 ? {} : { resource: failure.resource },
|
|
151
153
|
...failure.http_status === void 0 ? {} : { httpStatus: failure.http_status },
|
|
152
154
|
...failure.transport === void 0 ? {} : { transport: failure.transport },
|
|
@@ -161,6 +163,8 @@ const eventDetails = ({ type, metadata }) => ({
|
|
|
161
163
|
...type === "RECOVERED" && metadata.previous_process_exit !== void 0 ? { previousProcessExit: metadata.previous_process_exit } : {}
|
|
162
164
|
});
|
|
163
165
|
const toEventHistoryRow = (row) => ({
|
|
166
|
+
...row.to_release_id == null ? {} : { toReleaseId: row.to_release_id },
|
|
167
|
+
...row.metadata.sdk_version == null ? {} : { sdkVersion: row.metadata.sdk_version },
|
|
164
168
|
appVersion: row.app_version,
|
|
165
169
|
channel: row.channel,
|
|
166
170
|
cohort: row.metadata.cohort,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/plugin-insights",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.28",
|
|
5
5
|
"description": "Hot Updater's Insights plugin: launch, download, and update failure events, for the server and the React Native app",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./client": {
|