@hot-updater/plugin-insights 1.0.0-rc.34 → 1.0.0-rc.36
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/index.cjs +2 -1
- package/dist/client/index.mjs +2 -1
- package/dist/server/domain.d.cts +10 -0
- package/dist/server/domain.d.mts +10 -0
- package/dist/server/eventInput.cjs +7 -0
- package/dist/server/eventInput.mjs +7 -0
- package/dist/server/eventRow.cjs +13 -1
- package/dist/server/eventRow.d.cts +2 -0
- package/dist/server/eventRow.d.mts +2 -0
- package/dist/server/eventRow.mjs +13 -2
- package/dist/server/index.d.cts +32 -0
- package/dist/server/index.d.mts +32 -0
- package/dist/server/modelTypes.d.cts +3 -0
- package/dist/server/modelTypes.d.mts +3 -0
- package/dist/server/overview.d.cts +3 -3
- package/dist/server/overview.d.mts +3 -3
- package/dist/server/provider.cjs +2 -0
- package/dist/server/provider.mjs +2 -0
- package/dist/server/reads.cjs +58 -26
- package/dist/server/reads.mjs +58 -26
- package/dist/server/recordEvent.cjs +20 -7
- package/dist/server/recordEvent.mjs +20 -7
- package/dist/server/schema.cjs +50 -0
- package/dist/server/schema.d.cts +64 -0
- package/dist/server/schema.d.mts +64 -0
- package/dist/server/schema.mjs +50 -0
- package/package.json +5 -5
package/dist/client/index.cjs
CHANGED
|
@@ -60,7 +60,8 @@ const insights = (options = {}) => {
|
|
|
60
60
|
appVersion,
|
|
61
61
|
cohort: context.getCohort(),
|
|
62
62
|
fingerprintHash: context.getFingerprintHash(),
|
|
63
|
-
sdkVersion: context.sdkVersion
|
|
63
|
+
sdkVersion: context.sdkVersion,
|
|
64
|
+
minBundleId: context.minBundleId
|
|
64
65
|
};
|
|
65
66
|
const day = require_state.utcDay(now);
|
|
66
67
|
return {
|
package/dist/client/index.mjs
CHANGED
|
@@ -59,7 +59,8 @@ const insights = (options = {}) => {
|
|
|
59
59
|
appVersion,
|
|
60
60
|
cohort: context.getCohort(),
|
|
61
61
|
fingerprintHash: context.getFingerprintHash(),
|
|
62
|
-
sdkVersion: context.sdkVersion
|
|
62
|
+
sdkVersion: context.sdkVersion,
|
|
63
|
+
minBundleId: context.minBundleId
|
|
63
64
|
};
|
|
64
65
|
const day = utcDay(now);
|
|
65
66
|
return {
|
package/dist/server/domain.d.cts
CHANGED
|
@@ -44,6 +44,12 @@ type CreateBundleEventRequestBase = {
|
|
|
44
44
|
readonly cohort: string;
|
|
45
45
|
readonly fingerprintHash: string | null;
|
|
46
46
|
readonly sdkVersion?: string | null;
|
|
47
|
+
/**
|
|
48
|
+
* The bundle ID the native build ships as its built-in bundle. A report
|
|
49
|
+
* whose running bundle is this one, with no Release, runs the built-in
|
|
50
|
+
* bundle. Older SDKs leave it out.
|
|
51
|
+
*/
|
|
52
|
+
readonly minBundleId?: string | null;
|
|
47
53
|
readonly fromReleaseId: string | null;
|
|
48
54
|
readonly toReleaseId: string | null;
|
|
49
55
|
};
|
|
@@ -79,6 +85,8 @@ type ActiveInstallationWindow = "24h" | "7d" | "30d";
|
|
|
79
85
|
type EventHistoryRow = {
|
|
80
86
|
readonly toReleaseId?: string;
|
|
81
87
|
readonly sdkVersion?: string;
|
|
88
|
+
/** The native build's built-in bundle ID, when the SDK reported it. */
|
|
89
|
+
readonly minBundleId?: string;
|
|
82
90
|
readonly id: string;
|
|
83
91
|
readonly installId: string;
|
|
84
92
|
readonly type: "UPDATE_DOWNLOADED" | "UPDATE_APPLIED" | "RECOVERED" | "UPDATE_FAILED" | "UNCHANGED";
|
|
@@ -107,6 +115,8 @@ type InsightsHttpResponse = UpdateHttpResponse & {
|
|
|
107
115
|
};
|
|
108
116
|
type InstallationRow = {
|
|
109
117
|
readonly httpResponse?: InsightsHttpResponse;
|
|
118
|
+
/** The native build's built-in bundle ID, when the SDK reported it. */
|
|
119
|
+
readonly minBundleId?: string;
|
|
110
120
|
readonly installId: string;
|
|
111
121
|
readonly userId: string | null;
|
|
112
122
|
readonly lastKnownBundleId: string;
|
package/dist/server/domain.d.mts
CHANGED
|
@@ -44,6 +44,12 @@ type CreateBundleEventRequestBase = {
|
|
|
44
44
|
readonly cohort: string;
|
|
45
45
|
readonly fingerprintHash: string | null;
|
|
46
46
|
readonly sdkVersion?: string | null;
|
|
47
|
+
/**
|
|
48
|
+
* The bundle ID the native build ships as its built-in bundle. A report
|
|
49
|
+
* whose running bundle is this one, with no Release, runs the built-in
|
|
50
|
+
* bundle. Older SDKs leave it out.
|
|
51
|
+
*/
|
|
52
|
+
readonly minBundleId?: string | null;
|
|
47
53
|
readonly fromReleaseId: string | null;
|
|
48
54
|
readonly toReleaseId: string | null;
|
|
49
55
|
};
|
|
@@ -79,6 +85,8 @@ type ActiveInstallationWindow = "24h" | "7d" | "30d";
|
|
|
79
85
|
type EventHistoryRow = {
|
|
80
86
|
readonly toReleaseId?: string;
|
|
81
87
|
readonly sdkVersion?: string;
|
|
88
|
+
/** The native build's built-in bundle ID, when the SDK reported it. */
|
|
89
|
+
readonly minBundleId?: string;
|
|
82
90
|
readonly id: string;
|
|
83
91
|
readonly installId: string;
|
|
84
92
|
readonly type: "UPDATE_DOWNLOADED" | "UPDATE_APPLIED" | "RECOVERED" | "UPDATE_FAILED" | "UNCHANGED";
|
|
@@ -107,6 +115,8 @@ type InsightsHttpResponse = UpdateHttpResponse & {
|
|
|
107
115
|
};
|
|
108
116
|
type InstallationRow = {
|
|
109
117
|
readonly httpResponse?: InsightsHttpResponse;
|
|
118
|
+
/** The native build's built-in bundle ID, when the SDK reported it. */
|
|
119
|
+
readonly minBundleId?: string;
|
|
110
120
|
readonly installId: string;
|
|
111
121
|
readonly userId: string | null;
|
|
112
122
|
readonly lastKnownBundleId: string;
|
|
@@ -31,6 +31,11 @@ function readEventId(payload) {
|
|
|
31
31
|
if (!(0, _hot_updater_plugin_core.isUUIDv7)(value)) throw new require_errors.InsightsBadRequestError("Invalid event field: eventId");
|
|
32
32
|
return value;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The native build's built-in bundle ID: a bundle ID's length at most, and
|
|
36
|
+
* left out when it is missing or malformed, so the report still records.
|
|
37
|
+
*/
|
|
38
|
+
const readMinBundleId = (value) => typeof value === "string" && value.length > 0 && value.length <= 36 ? value : null;
|
|
34
39
|
/** One value of an open set: any other value reads as `unknown`. */
|
|
35
40
|
const oneOf = (values, value) => values.includes(value) ? value : "unknown";
|
|
36
41
|
const STAGES = [
|
|
@@ -156,6 +161,7 @@ function requireEvent(payload) {
|
|
|
156
161
|
cohort: requireStringField(payload, "cohort"),
|
|
157
162
|
fingerprintHash: requireNullableStringField(payload, "fingerprintHash"),
|
|
158
163
|
sdkVersion: payload.sdkVersion === void 0 ? null : requireNullableStringField(payload, "sdkVersion"),
|
|
164
|
+
minBundleId: readMinBundleId(payload.minBundleId),
|
|
159
165
|
fromReleaseId: requireNullableStringField(payload, "fromReleaseId"),
|
|
160
166
|
toReleaseId: requireNullableStringField(payload, "toReleaseId")
|
|
161
167
|
};
|
|
@@ -237,6 +243,7 @@ function createBundleEventRow(input) {
|
|
|
237
243
|
cohort: input.cohort,
|
|
238
244
|
fingerprint_hash: input.fingerprintHash,
|
|
239
245
|
sdk_version: input.sdkVersion ?? null,
|
|
246
|
+
...input.minBundleId ? { min_bundle_id: input.minBundleId } : {},
|
|
240
247
|
update_strategy: input.updateStrategy
|
|
241
248
|
};
|
|
242
249
|
switch (input.type) {
|
|
@@ -31,6 +31,11 @@ function readEventId(payload) {
|
|
|
31
31
|
if (!isUUIDv7(value)) throw new InsightsBadRequestError("Invalid event field: eventId");
|
|
32
32
|
return value;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The native build's built-in bundle ID: a bundle ID's length at most, and
|
|
36
|
+
* left out when it is missing or malformed, so the report still records.
|
|
37
|
+
*/
|
|
38
|
+
const readMinBundleId = (value) => typeof value === "string" && value.length > 0 && value.length <= 36 ? value : null;
|
|
34
39
|
/** One value of an open set: any other value reads as `unknown`. */
|
|
35
40
|
const oneOf = (values, value) => values.includes(value) ? value : "unknown";
|
|
36
41
|
const STAGES = [
|
|
@@ -156,6 +161,7 @@ function requireEvent(payload) {
|
|
|
156
161
|
cohort: requireStringField(payload, "cohort"),
|
|
157
162
|
fingerprintHash: requireNullableStringField(payload, "fingerprintHash"),
|
|
158
163
|
sdkVersion: payload.sdkVersion === void 0 ? null : requireNullableStringField(payload, "sdkVersion"),
|
|
164
|
+
minBundleId: readMinBundleId(payload.minBundleId),
|
|
159
165
|
fromReleaseId: requireNullableStringField(payload, "fromReleaseId"),
|
|
160
166
|
toReleaseId: requireNullableStringField(payload, "toReleaseId")
|
|
161
167
|
};
|
|
@@ -237,6 +243,7 @@ function createBundleEventRow(input) {
|
|
|
237
243
|
cohort: input.cohort,
|
|
238
244
|
fingerprint_hash: input.fingerprintHash,
|
|
239
245
|
sdk_version: input.sdkVersion ?? null,
|
|
246
|
+
...input.minBundleId ? { min_bundle_id: input.minBundleId } : {},
|
|
240
247
|
update_strategy: input.updateStrategy
|
|
241
248
|
};
|
|
242
249
|
switch (input.type) {
|
package/dist/server/eventRow.cjs
CHANGED
|
@@ -5,8 +5,19 @@ const isString = (value) => typeof value === "string";
|
|
|
5
5
|
const isDatabaseHttpResponse = (value) => (0, _hot_updater_plugin_core.isDatabaseJsonObject)(value) && (value.resource === "catalog" || value.resource === "artifact") && isString(value.path) && Number.isSafeInteger(value.status) && (value.body === null || isString(value.body)) && typeof value.body_truncated === "boolean" && Number.isSafeInteger(value.received_at_ms);
|
|
6
6
|
/** An `UPDATE_FAILED` report's stored failure: a stage and a reason, and what else the client knew. */
|
|
7
7
|
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);
|
|
8
|
-
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, "http_response", isDatabaseHttpResponse) && isOptional(value, "delivery", isString) && isOptional(value, "patch_fallback", (flag) => typeof flag === "boolean");
|
|
8
|
+
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, "min_bundle_id", isString) && isOptional(value, "failure", isDatabaseBundleEventFailure) && isOptional(value, "http_response", isDatabaseHttpResponse) && isOptional(value, "delivery", isString) && isOptional(value, "patch_fallback", (flag) => typeof flag === "boolean");
|
|
9
9
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10
|
+
/**
|
|
11
|
+
* The built-in bundle a report says its installation runs: the running
|
|
12
|
+
* bundle, which a download leaves at its source, when it is the native
|
|
13
|
+
* build's built-in bundle, whatever Release selected it. Null for any other
|
|
14
|
+
* bundle, and for a report without the build's built-in bundle ID.
|
|
15
|
+
*/
|
|
16
|
+
const runningBuiltinBundleId = (row) => {
|
|
17
|
+
const running = row.type === "UPDATE_DOWNLOADED" ? row.from_bundle_id : row.to_bundle_id;
|
|
18
|
+
const builtin = isRecord(row.metadata) ? row.metadata.min_bundle_id : null;
|
|
19
|
+
return typeof builtin === "string" && running === builtin ? builtin : null;
|
|
20
|
+
};
|
|
10
21
|
const isIdentity = (value) => typeof value === "string" && value.length > 0 && value.length <= 255;
|
|
11
22
|
const isTextOrNull = (value) => value === null || typeof value === "string";
|
|
12
23
|
/** Each bundle event field and what it holds. */
|
|
@@ -46,4 +57,5 @@ const validateBundleEventFields = (row) => {
|
|
|
46
57
|
//#endregion
|
|
47
58
|
exports.isDatabaseBundleEventMetadata = isDatabaseBundleEventMetadata;
|
|
48
59
|
exports.isRecord = isRecord;
|
|
60
|
+
exports.runningBuiltinBundleId = runningBuiltinBundleId;
|
|
49
61
|
exports.validateBundleEventFields = validateBundleEventFields;
|
|
@@ -31,6 +31,8 @@ type DatabaseBundleEventMetadata = DatabaseJsonObject & {
|
|
|
31
31
|
readonly update_strategy: "fingerprint" | "appVersion" | null;
|
|
32
32
|
readonly fingerprint_hash: string | null;
|
|
33
33
|
readonly sdk_version: string | null;
|
|
34
|
+
/** The native build's built-in bundle ID, when the SDK reports it. */
|
|
35
|
+
readonly min_bundle_id?: string;
|
|
34
36
|
/** `UPDATE_FAILED`: what failed. */
|
|
35
37
|
readonly failure?: BundleEventFailure;
|
|
36
38
|
readonly http_response?: DatabaseHttpResponse;
|
|
@@ -31,6 +31,8 @@ type DatabaseBundleEventMetadata = DatabaseJsonObject & {
|
|
|
31
31
|
readonly update_strategy: "fingerprint" | "appVersion" | null;
|
|
32
32
|
readonly fingerprint_hash: string | null;
|
|
33
33
|
readonly sdk_version: string | null;
|
|
34
|
+
/** The native build's built-in bundle ID, when the SDK reports it. */
|
|
35
|
+
readonly min_bundle_id?: string;
|
|
34
36
|
/** `UPDATE_FAILED`: what failed. */
|
|
35
37
|
readonly failure?: BundleEventFailure;
|
|
36
38
|
readonly http_response?: DatabaseHttpResponse;
|
package/dist/server/eventRow.mjs
CHANGED
|
@@ -5,8 +5,19 @@ const isString = (value) => typeof value === "string";
|
|
|
5
5
|
const isDatabaseHttpResponse = (value) => isDatabaseJsonObject(value) && (value.resource === "catalog" || value.resource === "artifact") && isString(value.path) && Number.isSafeInteger(value.status) && (value.body === null || isString(value.body)) && typeof value.body_truncated === "boolean" && Number.isSafeInteger(value.received_at_ms);
|
|
6
6
|
/** An `UPDATE_FAILED` report's stored failure: a stage and a reason, and what else the client knew. */
|
|
7
7
|
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);
|
|
8
|
-
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, "http_response", isDatabaseHttpResponse) && isOptional(value, "delivery", isString) && isOptional(value, "patch_fallback", (flag) => typeof flag === "boolean");
|
|
8
|
+
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, "min_bundle_id", isString) && isOptional(value, "failure", isDatabaseBundleEventFailure) && isOptional(value, "http_response", isDatabaseHttpResponse) && isOptional(value, "delivery", isString) && isOptional(value, "patch_fallback", (flag) => typeof flag === "boolean");
|
|
9
9
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10
|
+
/**
|
|
11
|
+
* The built-in bundle a report says its installation runs: the running
|
|
12
|
+
* bundle, which a download leaves at its source, when it is the native
|
|
13
|
+
* build's built-in bundle, whatever Release selected it. Null for any other
|
|
14
|
+
* bundle, and for a report without the build's built-in bundle ID.
|
|
15
|
+
*/
|
|
16
|
+
const runningBuiltinBundleId = (row) => {
|
|
17
|
+
const running = row.type === "UPDATE_DOWNLOADED" ? row.from_bundle_id : row.to_bundle_id;
|
|
18
|
+
const builtin = isRecord(row.metadata) ? row.metadata.min_bundle_id : null;
|
|
19
|
+
return typeof builtin === "string" && running === builtin ? builtin : null;
|
|
20
|
+
};
|
|
10
21
|
const isIdentity = (value) => typeof value === "string" && value.length > 0 && value.length <= 255;
|
|
11
22
|
const isTextOrNull = (value) => value === null || typeof value === "string";
|
|
12
23
|
/** Each bundle event field and what it holds. */
|
|
@@ -44,4 +55,4 @@ const validateBundleEventFields = (row) => {
|
|
|
44
55
|
if (!hasEventInvariants(row)) throw new DatabaseAdapterInputError("invalid-data");
|
|
45
56
|
};
|
|
46
57
|
//#endregion
|
|
47
|
-
export { isDatabaseBundleEventMetadata, isRecord, validateBundleEventFields };
|
|
58
|
+
export { isDatabaseBundleEventMetadata, isRecord, runningBuiltinBundleId, validateBundleEventFields };
|
package/dist/server/index.d.cts
CHANGED
|
@@ -284,6 +284,38 @@ declare const insights: (options?: InsightsOptions) => import("@hot-updater/plug
|
|
|
284
284
|
readonly sort: readonly ["bucket_start_ms"];
|
|
285
285
|
};
|
|
286
286
|
}, never, readonly ["channel", "platform", "app_version", "release_id", "bucket_start_ms"]>;
|
|
287
|
+
readonly insights_builtin_distribution: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
288
|
+
readonly channel: {
|
|
289
|
+
readonly type: "string";
|
|
290
|
+
};
|
|
291
|
+
readonly platform: {
|
|
292
|
+
readonly type: "string";
|
|
293
|
+
readonly maxLength: 16;
|
|
294
|
+
};
|
|
295
|
+
readonly app_version: {
|
|
296
|
+
readonly type: "string";
|
|
297
|
+
};
|
|
298
|
+
readonly release_id: {
|
|
299
|
+
readonly type: "string";
|
|
300
|
+
readonly maxLength: 36;
|
|
301
|
+
};
|
|
302
|
+
readonly builtin_bundle_id: {
|
|
303
|
+
readonly type: "string";
|
|
304
|
+
readonly maxLength: 36;
|
|
305
|
+
};
|
|
306
|
+
readonly bucket_start_ms: {
|
|
307
|
+
readonly type: "integer";
|
|
308
|
+
};
|
|
309
|
+
}, "latest_installations", {
|
|
310
|
+
readonly byScope: {
|
|
311
|
+
readonly eq: readonly ["channel", "platform"];
|
|
312
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
313
|
+
};
|
|
314
|
+
readonly byVersion: {
|
|
315
|
+
readonly eq: readonly ["channel", "platform", "app_version"];
|
|
316
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
317
|
+
};
|
|
318
|
+
}, never, readonly ["channel", "platform", "app_version", "release_id", "builtin_bundle_id", "bucket_start_ms"]>;
|
|
287
319
|
readonly insights_latest_by_bundle: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
288
320
|
readonly platform: {
|
|
289
321
|
readonly type: "string";
|
package/dist/server/index.d.mts
CHANGED
|
@@ -284,6 +284,38 @@ declare const insights: (options?: InsightsOptions) => import("@hot-updater/plug
|
|
|
284
284
|
readonly sort: readonly ["bucket_start_ms"];
|
|
285
285
|
};
|
|
286
286
|
}, never, readonly ["channel", "platform", "app_version", "release_id", "bucket_start_ms"]>;
|
|
287
|
+
readonly insights_builtin_distribution: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
288
|
+
readonly channel: {
|
|
289
|
+
readonly type: "string";
|
|
290
|
+
};
|
|
291
|
+
readonly platform: {
|
|
292
|
+
readonly type: "string";
|
|
293
|
+
readonly maxLength: 16;
|
|
294
|
+
};
|
|
295
|
+
readonly app_version: {
|
|
296
|
+
readonly type: "string";
|
|
297
|
+
};
|
|
298
|
+
readonly release_id: {
|
|
299
|
+
readonly type: "string";
|
|
300
|
+
readonly maxLength: 36;
|
|
301
|
+
};
|
|
302
|
+
readonly builtin_bundle_id: {
|
|
303
|
+
readonly type: "string";
|
|
304
|
+
readonly maxLength: 36;
|
|
305
|
+
};
|
|
306
|
+
readonly bucket_start_ms: {
|
|
307
|
+
readonly type: "integer";
|
|
308
|
+
};
|
|
309
|
+
}, "latest_installations", {
|
|
310
|
+
readonly byScope: {
|
|
311
|
+
readonly eq: readonly ["channel", "platform"];
|
|
312
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
313
|
+
};
|
|
314
|
+
readonly byVersion: {
|
|
315
|
+
readonly eq: readonly ["channel", "platform", "app_version"];
|
|
316
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
317
|
+
};
|
|
318
|
+
}, never, readonly ["channel", "platform", "app_version", "release_id", "builtin_bundle_id", "bucket_start_ms"]>;
|
|
287
319
|
readonly insights_latest_by_bundle: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
288
320
|
readonly platform: {
|
|
289
321
|
readonly type: "string";
|
|
@@ -139,7 +139,10 @@ interface InsightsGetAppUsageResult {
|
|
|
139
139
|
readonly bundleDistribution: readonly {
|
|
140
140
|
readonly appVersion: string;
|
|
141
141
|
readonly platform: "ios" | "android";
|
|
142
|
+
/** The release the installations run; null for none. */
|
|
142
143
|
readonly releaseId: string | null;
|
|
144
|
+
/** The native build's built-in bundle, when they run it. */
|
|
145
|
+
readonly builtinBundleId: string | null;
|
|
143
146
|
readonly installations: number;
|
|
144
147
|
}[];
|
|
145
148
|
readonly measuredAtMs: number;
|
|
@@ -139,7 +139,10 @@ interface InsightsGetAppUsageResult {
|
|
|
139
139
|
readonly bundleDistribution: readonly {
|
|
140
140
|
readonly appVersion: string;
|
|
141
141
|
readonly platform: "ios" | "android";
|
|
142
|
+
/** The release the installations run; null for none. */
|
|
142
143
|
readonly releaseId: string | null;
|
|
144
|
+
/** The native build's built-in bundle, when they run it. */
|
|
145
|
+
readonly builtinBundleId: string | null;
|
|
143
146
|
readonly installations: number;
|
|
144
147
|
}[];
|
|
145
148
|
readonly measuredAtMs: number;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import "./eventRow.cjs";
|
|
2
2
|
//#region src/server/overview.d.ts
|
|
3
3
|
type InsightsOverviewIdentity = {
|
|
4
|
-
readonly scopeKind: "release" | "channel" | "usage"
|
|
5
|
-
readonly releaseKind: "all" | "specific"
|
|
4
|
+
readonly scopeKind: "release" | "channel" | "usage";
|
|
5
|
+
readonly releaseKind: "all" | "specific";
|
|
6
6
|
readonly releaseId: string;
|
|
7
7
|
readonly channel: string;
|
|
8
8
|
readonly platform: "all" | "ios" | "android";
|
|
9
9
|
readonly appVersionKind: "all" | "specific";
|
|
10
10
|
readonly appVersion: string;
|
|
11
|
-
readonly periodKind: "lifetime" | "hour"
|
|
11
|
+
readonly periodKind: "lifetime" | "hour";
|
|
12
12
|
readonly bucketStartMs: number;
|
|
13
13
|
};
|
|
14
14
|
//#endregion
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import "./eventRow.mjs";
|
|
2
2
|
//#region src/server/overview.d.ts
|
|
3
3
|
type InsightsOverviewIdentity = {
|
|
4
|
-
readonly scopeKind: "release" | "channel" | "usage"
|
|
5
|
-
readonly releaseKind: "all" | "specific"
|
|
4
|
+
readonly scopeKind: "release" | "channel" | "usage";
|
|
5
|
+
readonly releaseKind: "all" | "specific";
|
|
6
6
|
readonly releaseId: string;
|
|
7
7
|
readonly channel: string;
|
|
8
8
|
readonly platform: "all" | "ios" | "android";
|
|
9
9
|
readonly appVersionKind: "all" | "specific";
|
|
10
10
|
readonly appVersion: string;
|
|
11
|
-
readonly periodKind: "lifetime" | "hour"
|
|
11
|
+
readonly periodKind: "lifetime" | "hour";
|
|
12
12
|
readonly bucketStartMs: number;
|
|
13
13
|
};
|
|
14
14
|
//#endregion
|
package/dist/server/provider.cjs
CHANGED
|
@@ -171,6 +171,7 @@ const eventDetails = ({ type, metadata }) => ({
|
|
|
171
171
|
const toEventHistoryRow = (row) => ({
|
|
172
172
|
...row.to_release_id == null ? {} : { toReleaseId: row.to_release_id },
|
|
173
173
|
...row.metadata.sdk_version == null ? {} : { sdkVersion: row.metadata.sdk_version },
|
|
174
|
+
...row.metadata.min_bundle_id === void 0 ? {} : { minBundleId: row.metadata.min_bundle_id },
|
|
174
175
|
appVersion: row.app_version,
|
|
175
176
|
channel: row.channel,
|
|
176
177
|
cohort: row.metadata.cohort,
|
|
@@ -186,6 +187,7 @@ const toEventHistoryRow = (row) => ({
|
|
|
186
187
|
});
|
|
187
188
|
const toInstallationRow = (row) => ({
|
|
188
189
|
...eventDetails(row).httpResponse ? { httpResponse: eventDetails(row).httpResponse } : {},
|
|
190
|
+
...row.metadata.min_bundle_id === void 0 ? {} : { minBundleId: row.metadata.min_bundle_id },
|
|
189
191
|
appVersion: row.app_version,
|
|
190
192
|
channel: row.channel,
|
|
191
193
|
cohort: row.metadata.cohort,
|
package/dist/server/provider.mjs
CHANGED
|
@@ -171,6 +171,7 @@ const eventDetails = ({ type, metadata }) => ({
|
|
|
171
171
|
const toEventHistoryRow = (row) => ({
|
|
172
172
|
...row.to_release_id == null ? {} : { toReleaseId: row.to_release_id },
|
|
173
173
|
...row.metadata.sdk_version == null ? {} : { sdkVersion: row.metadata.sdk_version },
|
|
174
|
+
...row.metadata.min_bundle_id === void 0 ? {} : { minBundleId: row.metadata.min_bundle_id },
|
|
174
175
|
appVersion: row.app_version,
|
|
175
176
|
channel: row.channel,
|
|
176
177
|
cohort: row.metadata.cohort,
|
|
@@ -186,6 +187,7 @@ const toEventHistoryRow = (row) => ({
|
|
|
186
187
|
});
|
|
187
188
|
const toInstallationRow = (row) => ({
|
|
188
189
|
...eventDetails(row).httpResponse ? { httpResponse: eventDetails(row).httpResponse } : {},
|
|
190
|
+
...row.metadata.min_bundle_id === void 0 ? {} : { minBundleId: row.metadata.min_bundle_id },
|
|
189
191
|
appVersion: row.app_version,
|
|
190
192
|
channel: row.channel,
|
|
191
193
|
cohort: row.metadata.cohort,
|
package/dist/server/reads.cjs
CHANGED
|
@@ -410,26 +410,49 @@ const getAppUsage = async (db, input, now, retention) => {
|
|
|
410
410
|
lt: timeRange.end
|
|
411
411
|
};
|
|
412
412
|
const distribution = [];
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
413
|
+
const builtinDistribution = [];
|
|
414
|
+
for (const platform of reported) {
|
|
415
|
+
distribution.push(...await drain((page) => input.appVersion === void 0 ? db.findAggregates("insights_distribution", {
|
|
416
|
+
index: "byScope",
|
|
417
|
+
where: {
|
|
418
|
+
channel: input.channel,
|
|
419
|
+
platform
|
|
420
|
+
},
|
|
421
|
+
range,
|
|
422
|
+
limit: PAGE,
|
|
423
|
+
...page
|
|
424
|
+
}) : db.findAggregates("insights_distribution", {
|
|
425
|
+
index: "byVersion",
|
|
426
|
+
where: {
|
|
427
|
+
channel: input.channel,
|
|
428
|
+
platform,
|
|
429
|
+
app_version: input.appVersion
|
|
430
|
+
},
|
|
431
|
+
range,
|
|
432
|
+
limit: PAGE,
|
|
433
|
+
...page
|
|
434
|
+
})));
|
|
435
|
+
builtinDistribution.push(...await drain((page) => input.appVersion === void 0 ? db.findAggregates("insights_builtin_distribution", {
|
|
436
|
+
index: "byScope",
|
|
437
|
+
where: {
|
|
438
|
+
channel: input.channel,
|
|
439
|
+
platform
|
|
440
|
+
},
|
|
441
|
+
range,
|
|
442
|
+
limit: PAGE,
|
|
443
|
+
...page
|
|
444
|
+
}) : db.findAggregates("insights_builtin_distribution", {
|
|
445
|
+
index: "byVersion",
|
|
446
|
+
where: {
|
|
447
|
+
channel: input.channel,
|
|
448
|
+
platform,
|
|
449
|
+
app_version: input.appVersion
|
|
450
|
+
},
|
|
451
|
+
range,
|
|
452
|
+
limit: PAGE,
|
|
453
|
+
...page
|
|
454
|
+
})));
|
|
455
|
+
}
|
|
433
456
|
const points = [];
|
|
434
457
|
for (let start = timeRange.start; start < timeRange.end; start += intervalMs) points.push({
|
|
435
458
|
startMs: start,
|
|
@@ -438,22 +461,31 @@ const getAppUsage = async (db, input, now, retention) => {
|
|
|
438
461
|
const versions = /* @__PURE__ */ new Map();
|
|
439
462
|
const platforms = /* @__PURE__ */ new Map();
|
|
440
463
|
const bundles = /* @__PURE__ */ new Map();
|
|
441
|
-
|
|
442
|
-
const count = row.latest_installations;
|
|
443
|
-
versions.set(row.app_version, (versions.get(row.app_version) ?? 0) + count);
|
|
444
|
-
platforms.set(row.platform, (platforms.get(row.platform) ?? 0) + count);
|
|
445
|
-
const releaseId = row.release_id === "" ? null : row.release_id;
|
|
464
|
+
const countBundle = (row, releaseId, builtinBundleId, count) => {
|
|
446
465
|
const key = JSON.stringify([
|
|
447
466
|
row.app_version,
|
|
448
467
|
row.platform,
|
|
449
|
-
releaseId
|
|
468
|
+
releaseId,
|
|
469
|
+
builtinBundleId
|
|
450
470
|
]);
|
|
451
471
|
bundles.set(key, {
|
|
452
472
|
appVersion: row.app_version,
|
|
453
473
|
platform: row.platform,
|
|
454
474
|
releaseId,
|
|
475
|
+
builtinBundleId,
|
|
455
476
|
installations: (bundles.get(key)?.installations ?? 0) + count
|
|
456
477
|
});
|
|
478
|
+
};
|
|
479
|
+
for (const row of distribution) {
|
|
480
|
+
const count = row.latest_installations;
|
|
481
|
+
versions.set(row.app_version, (versions.get(row.app_version) ?? 0) + count);
|
|
482
|
+
platforms.set(row.platform, (platforms.get(row.platform) ?? 0) + count);
|
|
483
|
+
countBundle(row, row.release_id || null, null, count);
|
|
484
|
+
}
|
|
485
|
+
for (const row of builtinDistribution) {
|
|
486
|
+
const releaseId = row.release_id || null;
|
|
487
|
+
countBundle(row, releaseId, null, -row.latest_installations);
|
|
488
|
+
countBundle(row, releaseId, row.builtin_bundle_id, row.latest_installations);
|
|
457
489
|
}
|
|
458
490
|
const sortedVersions = byInstallations(versions);
|
|
459
491
|
return {
|
package/dist/server/reads.mjs
CHANGED
|
@@ -410,26 +410,49 @@ const getAppUsage = async (db, input, now, retention) => {
|
|
|
410
410
|
lt: timeRange.end
|
|
411
411
|
};
|
|
412
412
|
const distribution = [];
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
413
|
+
const builtinDistribution = [];
|
|
414
|
+
for (const platform of reported) {
|
|
415
|
+
distribution.push(...await drain((page) => input.appVersion === void 0 ? db.findAggregates("insights_distribution", {
|
|
416
|
+
index: "byScope",
|
|
417
|
+
where: {
|
|
418
|
+
channel: input.channel,
|
|
419
|
+
platform
|
|
420
|
+
},
|
|
421
|
+
range,
|
|
422
|
+
limit: PAGE,
|
|
423
|
+
...page
|
|
424
|
+
}) : db.findAggregates("insights_distribution", {
|
|
425
|
+
index: "byVersion",
|
|
426
|
+
where: {
|
|
427
|
+
channel: input.channel,
|
|
428
|
+
platform,
|
|
429
|
+
app_version: input.appVersion
|
|
430
|
+
},
|
|
431
|
+
range,
|
|
432
|
+
limit: PAGE,
|
|
433
|
+
...page
|
|
434
|
+
})));
|
|
435
|
+
builtinDistribution.push(...await drain((page) => input.appVersion === void 0 ? db.findAggregates("insights_builtin_distribution", {
|
|
436
|
+
index: "byScope",
|
|
437
|
+
where: {
|
|
438
|
+
channel: input.channel,
|
|
439
|
+
platform
|
|
440
|
+
},
|
|
441
|
+
range,
|
|
442
|
+
limit: PAGE,
|
|
443
|
+
...page
|
|
444
|
+
}) : db.findAggregates("insights_builtin_distribution", {
|
|
445
|
+
index: "byVersion",
|
|
446
|
+
where: {
|
|
447
|
+
channel: input.channel,
|
|
448
|
+
platform,
|
|
449
|
+
app_version: input.appVersion
|
|
450
|
+
},
|
|
451
|
+
range,
|
|
452
|
+
limit: PAGE,
|
|
453
|
+
...page
|
|
454
|
+
})));
|
|
455
|
+
}
|
|
433
456
|
const points = [];
|
|
434
457
|
for (let start = timeRange.start; start < timeRange.end; start += intervalMs) points.push({
|
|
435
458
|
startMs: start,
|
|
@@ -438,22 +461,31 @@ const getAppUsage = async (db, input, now, retention) => {
|
|
|
438
461
|
const versions = /* @__PURE__ */ new Map();
|
|
439
462
|
const platforms = /* @__PURE__ */ new Map();
|
|
440
463
|
const bundles = /* @__PURE__ */ new Map();
|
|
441
|
-
|
|
442
|
-
const count = row.latest_installations;
|
|
443
|
-
versions.set(row.app_version, (versions.get(row.app_version) ?? 0) + count);
|
|
444
|
-
platforms.set(row.platform, (platforms.get(row.platform) ?? 0) + count);
|
|
445
|
-
const releaseId = row.release_id === "" ? null : row.release_id;
|
|
464
|
+
const countBundle = (row, releaseId, builtinBundleId, count) => {
|
|
446
465
|
const key = JSON.stringify([
|
|
447
466
|
row.app_version,
|
|
448
467
|
row.platform,
|
|
449
|
-
releaseId
|
|
468
|
+
releaseId,
|
|
469
|
+
builtinBundleId
|
|
450
470
|
]);
|
|
451
471
|
bundles.set(key, {
|
|
452
472
|
appVersion: row.app_version,
|
|
453
473
|
platform: row.platform,
|
|
454
474
|
releaseId,
|
|
475
|
+
builtinBundleId,
|
|
455
476
|
installations: (bundles.get(key)?.installations ?? 0) + count
|
|
456
477
|
});
|
|
478
|
+
};
|
|
479
|
+
for (const row of distribution) {
|
|
480
|
+
const count = row.latest_installations;
|
|
481
|
+
versions.set(row.app_version, (versions.get(row.app_version) ?? 0) + count);
|
|
482
|
+
platforms.set(row.platform, (platforms.get(row.platform) ?? 0) + count);
|
|
483
|
+
countBundle(row, row.release_id || null, null, count);
|
|
484
|
+
}
|
|
485
|
+
for (const row of builtinDistribution) {
|
|
486
|
+
const releaseId = row.release_id || null;
|
|
487
|
+
countBundle(row, releaseId, null, -row.latest_installations);
|
|
488
|
+
countBundle(row, releaseId, row.builtin_bundle_id, row.latest_installations);
|
|
457
489
|
}
|
|
458
490
|
const sortedVersions = byInstallations(versions);
|
|
459
491
|
return {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const require_eventRow = require("./eventRow.cjs");
|
|
1
2
|
const require_contract = require("./contract.cjs");
|
|
2
3
|
const require_overview = require("./overview.cjs");
|
|
3
4
|
const require_schema = require("./schema.cjs");
|
|
@@ -13,13 +14,16 @@ const insightsIdentity = (identity) => require_overview.insightsOverviewId({
|
|
|
13
14
|
bucketStartMs: 0
|
|
14
15
|
});
|
|
15
16
|
/**
|
|
16
|
-
* The bucket a head's gauges count it in, the UTC day of its event, and
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* The bucket a head's gauges count it in, the UTC day of its event, and what
|
|
18
|
+
* its distribution row names: the release it runs, which a download leaves
|
|
19
|
+
* at its source, and the built-in bundle, when it runs the native build's.
|
|
20
|
+
* A head stored without the built-in bundle ID counts in no built-in row, so
|
|
21
|
+
* taking it back moves none.
|
|
19
22
|
*/
|
|
20
23
|
const gaugeSlot = (head) => ({
|
|
21
24
|
bucket: dayOf(head.received_at_ms),
|
|
22
|
-
releaseId: head.type === "UPDATE_DOWNLOADED" ? head.from_release_id : head.to_release_id
|
|
25
|
+
releaseId: head.type === "UPDATE_DOWNLOADED" ? head.from_release_id : head.to_release_id,
|
|
26
|
+
builtinBundleId: require_eventRow.runningBuiltinBundleId(head)
|
|
23
27
|
});
|
|
24
28
|
/**
|
|
25
29
|
* The `insights_latest_by_bundle` field of a head's (from, to) pair. A head
|
|
@@ -30,11 +34,12 @@ const PAIR_FIELD = "from_to";
|
|
|
30
34
|
/** The pair gauge's `bundle_id`: a hash of the two bundle ids, which fit no single 36-character column. */
|
|
31
35
|
const bundlePairKey = (from, to) => require_overview.insightsKey(`${from.length}:${from}${to.length}:${to}`);
|
|
32
36
|
/**
|
|
33
|
-
* Moves a head's gauges: the distribution row,
|
|
34
|
-
*
|
|
37
|
+
* Moves a head's gauges: the distribution row, and the built-in one when it
|
|
38
|
+
* runs its build's built-in bundle, one row per bundle it references, and
|
|
39
|
+
* its pair; -1 takes back the head an event replaces.
|
|
35
40
|
*/
|
|
36
41
|
const countHead = (tx, head, delta) => {
|
|
37
|
-
const { bucket, releaseId } = gaugeSlot(head);
|
|
42
|
+
const { bucket, releaseId, builtinBundleId } = gaugeSlot(head);
|
|
38
43
|
const shardBy = head.install_id;
|
|
39
44
|
tx.aggregate("insights_distribution", {
|
|
40
45
|
channel: head.channel,
|
|
@@ -43,6 +48,14 @@ const countHead = (tx, head, delta) => {
|
|
|
43
48
|
release_id: releaseId ?? "",
|
|
44
49
|
bucket_start_ms: bucket
|
|
45
50
|
}, { latest_installations: delta }, { shardBy });
|
|
51
|
+
if (builtinBundleId !== null) tx.aggregate("insights_builtin_distribution", {
|
|
52
|
+
channel: head.channel,
|
|
53
|
+
platform: head.platform,
|
|
54
|
+
app_version: head.app_version,
|
|
55
|
+
release_id: releaseId ?? "",
|
|
56
|
+
builtin_bundle_id: builtinBundleId,
|
|
57
|
+
bucket_start_ms: bucket
|
|
58
|
+
}, { latest_installations: delta }, { shardBy });
|
|
46
59
|
for (const field of ["from_bundle_id", "to_bundle_id"]) {
|
|
47
60
|
const bundleId = head[field];
|
|
48
61
|
if (bundleId === null) continue;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { runningBuiltinBundleId } from "./eventRow.mjs";
|
|
1
2
|
import { assertBundleEventRow } from "./contract.mjs";
|
|
2
3
|
import { insightsKey, insightsOverviewDeltas, insightsOverviewId } from "./overview.mjs";
|
|
3
4
|
import { DAILY_EVENTS, DAY_MS, HOUR_MS, isFailedCheck } from "./schema.mjs";
|
|
@@ -13,13 +14,16 @@ const insightsIdentity = (identity) => insightsOverviewId({
|
|
|
13
14
|
bucketStartMs: 0
|
|
14
15
|
});
|
|
15
16
|
/**
|
|
16
|
-
* The bucket a head's gauges count it in, the UTC day of its event, and
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* The bucket a head's gauges count it in, the UTC day of its event, and what
|
|
18
|
+
* its distribution row names: the release it runs, which a download leaves
|
|
19
|
+
* at its source, and the built-in bundle, when it runs the native build's.
|
|
20
|
+
* A head stored without the built-in bundle ID counts in no built-in row, so
|
|
21
|
+
* taking it back moves none.
|
|
19
22
|
*/
|
|
20
23
|
const gaugeSlot = (head) => ({
|
|
21
24
|
bucket: dayOf(head.received_at_ms),
|
|
22
|
-
releaseId: head.type === "UPDATE_DOWNLOADED" ? head.from_release_id : head.to_release_id
|
|
25
|
+
releaseId: head.type === "UPDATE_DOWNLOADED" ? head.from_release_id : head.to_release_id,
|
|
26
|
+
builtinBundleId: runningBuiltinBundleId(head)
|
|
23
27
|
});
|
|
24
28
|
/**
|
|
25
29
|
* The `insights_latest_by_bundle` field of a head's (from, to) pair. A head
|
|
@@ -30,11 +34,12 @@ const PAIR_FIELD = "from_to";
|
|
|
30
34
|
/** The pair gauge's `bundle_id`: a hash of the two bundle ids, which fit no single 36-character column. */
|
|
31
35
|
const bundlePairKey = (from, to) => insightsKey(`${from.length}:${from}${to.length}:${to}`);
|
|
32
36
|
/**
|
|
33
|
-
* Moves a head's gauges: the distribution row,
|
|
34
|
-
*
|
|
37
|
+
* Moves a head's gauges: the distribution row, and the built-in one when it
|
|
38
|
+
* runs its build's built-in bundle, one row per bundle it references, and
|
|
39
|
+
* its pair; -1 takes back the head an event replaces.
|
|
35
40
|
*/
|
|
36
41
|
const countHead = (tx, head, delta) => {
|
|
37
|
-
const { bucket, releaseId } = gaugeSlot(head);
|
|
42
|
+
const { bucket, releaseId, builtinBundleId } = gaugeSlot(head);
|
|
38
43
|
const shardBy = head.install_id;
|
|
39
44
|
tx.aggregate("insights_distribution", {
|
|
40
45
|
channel: head.channel,
|
|
@@ -43,6 +48,14 @@ const countHead = (tx, head, delta) => {
|
|
|
43
48
|
release_id: releaseId ?? "",
|
|
44
49
|
bucket_start_ms: bucket
|
|
45
50
|
}, { latest_installations: delta }, { shardBy });
|
|
51
|
+
if (builtinBundleId !== null) tx.aggregate("insights_builtin_distribution", {
|
|
52
|
+
channel: head.channel,
|
|
53
|
+
platform: head.platform,
|
|
54
|
+
app_version: head.app_version,
|
|
55
|
+
release_id: releaseId ?? "",
|
|
56
|
+
builtin_bundle_id: builtinBundleId,
|
|
57
|
+
bucket_start_ms: bucket
|
|
58
|
+
}, { latest_installations: delta }, { shardBy });
|
|
46
59
|
for (const field of ["from_bundle_id", "to_bundle_id"]) {
|
|
47
60
|
const bundleId = head[field];
|
|
48
61
|
if (bundleId === null) continue;
|
package/dist/server/schema.cjs
CHANGED
|
@@ -354,6 +354,55 @@ const insightsDistribution = (retention) => (0, _hot_updater_plugin_core.defineA
|
|
|
354
354
|
},
|
|
355
355
|
retention
|
|
356
356
|
});
|
|
357
|
+
/**
|
|
358
|
+
* The installations of `insights_distribution` that run their native build's
|
|
359
|
+
* built-in bundle, by its ID (`builtin_bundle_id`), within the same rows:
|
|
360
|
+
* reads move them out of the row of their release, or of no release.
|
|
361
|
+
*/
|
|
362
|
+
const insightsBuiltinDistribution = (retention) => (0, _hot_updater_plugin_core.defineAggregate)({
|
|
363
|
+
channel: { type: "string" },
|
|
364
|
+
platform: {
|
|
365
|
+
type: "string",
|
|
366
|
+
maxLength: 16
|
|
367
|
+
},
|
|
368
|
+
app_version: { type: "string" },
|
|
369
|
+
release_id: {
|
|
370
|
+
type: "string",
|
|
371
|
+
maxLength: 36
|
|
372
|
+
},
|
|
373
|
+
builtin_bundle_id: {
|
|
374
|
+
type: "string",
|
|
375
|
+
maxLength: 36
|
|
376
|
+
},
|
|
377
|
+
bucket_start_ms: { type: "integer" }
|
|
378
|
+
}, {
|
|
379
|
+
key: [
|
|
380
|
+
"channel",
|
|
381
|
+
"platform",
|
|
382
|
+
"app_version",
|
|
383
|
+
"release_id",
|
|
384
|
+
"builtin_bundle_id",
|
|
385
|
+
"bucket_start_ms"
|
|
386
|
+
],
|
|
387
|
+
gauges: ["latest_installations"],
|
|
388
|
+
shards: GAUGE_SHARDS,
|
|
389
|
+
batched: true,
|
|
390
|
+
indexes: {
|
|
391
|
+
byScope: {
|
|
392
|
+
eq: ["channel", "platform"],
|
|
393
|
+
sort: ["bucket_start_ms"]
|
|
394
|
+
},
|
|
395
|
+
byVersion: {
|
|
396
|
+
eq: [
|
|
397
|
+
"channel",
|
|
398
|
+
"platform",
|
|
399
|
+
"app_version"
|
|
400
|
+
],
|
|
401
|
+
sort: ["bucket_start_ms"]
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
retention
|
|
405
|
+
});
|
|
357
406
|
/** Latest events by the bundle they came from or went to, bucketed like the distribution. */
|
|
358
407
|
const insightsLatestByBundle = (retention) => (0, _hot_updater_plugin_core.defineAggregate)({
|
|
359
408
|
platform: {
|
|
@@ -473,6 +522,7 @@ const createInsightsSchema = ({ rawDays, dailyDays } = DEFAULT_INSIGHTS_RETENTIO
|
|
|
473
522
|
insights_overview_lifetime: lifetimeCounters(),
|
|
474
523
|
insights_sketches_lifetime: lifetimeSketches(),
|
|
475
524
|
insights_distribution: insightsDistribution(daily),
|
|
525
|
+
insights_builtin_distribution: insightsBuiltinDistribution(daily),
|
|
476
526
|
insights_latest_by_bundle: insightsLatestByBundle(daily),
|
|
477
527
|
insights_outcomes: insightsOutcomes(hourly),
|
|
478
528
|
insights_failures: insightsFailures(hourly)
|
package/dist/server/schema.d.cts
CHANGED
|
@@ -259,6 +259,38 @@ declare const createInsightsSchema: ({ rawDays, dailyDays }?: InsightsRetention)
|
|
|
259
259
|
readonly sort: readonly ["bucket_start_ms"];
|
|
260
260
|
};
|
|
261
261
|
}, never, readonly ["channel", "platform", "app_version", "release_id", "bucket_start_ms"]>;
|
|
262
|
+
readonly insights_builtin_distribution: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
263
|
+
readonly channel: {
|
|
264
|
+
readonly type: "string";
|
|
265
|
+
};
|
|
266
|
+
readonly platform: {
|
|
267
|
+
readonly type: "string";
|
|
268
|
+
readonly maxLength: 16;
|
|
269
|
+
};
|
|
270
|
+
readonly app_version: {
|
|
271
|
+
readonly type: "string";
|
|
272
|
+
};
|
|
273
|
+
readonly release_id: {
|
|
274
|
+
readonly type: "string";
|
|
275
|
+
readonly maxLength: 36;
|
|
276
|
+
};
|
|
277
|
+
readonly builtin_bundle_id: {
|
|
278
|
+
readonly type: "string";
|
|
279
|
+
readonly maxLength: 36;
|
|
280
|
+
};
|
|
281
|
+
readonly bucket_start_ms: {
|
|
282
|
+
readonly type: "integer";
|
|
283
|
+
};
|
|
284
|
+
}, "latest_installations", {
|
|
285
|
+
readonly byScope: {
|
|
286
|
+
readonly eq: readonly ["channel", "platform"];
|
|
287
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
288
|
+
};
|
|
289
|
+
readonly byVersion: {
|
|
290
|
+
readonly eq: readonly ["channel", "platform", "app_version"];
|
|
291
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
292
|
+
};
|
|
293
|
+
}, never, readonly ["channel", "platform", "app_version", "release_id", "builtin_bundle_id", "bucket_start_ms"]>;
|
|
262
294
|
readonly insights_latest_by_bundle: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
263
295
|
readonly platform: {
|
|
264
296
|
readonly type: "string";
|
|
@@ -594,6 +626,38 @@ declare const insightsSchema: {
|
|
|
594
626
|
readonly sort: readonly ["bucket_start_ms"];
|
|
595
627
|
};
|
|
596
628
|
}, never, readonly ["channel", "platform", "app_version", "release_id", "bucket_start_ms"]>;
|
|
629
|
+
readonly insights_builtin_distribution: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
630
|
+
readonly channel: {
|
|
631
|
+
readonly type: "string";
|
|
632
|
+
};
|
|
633
|
+
readonly platform: {
|
|
634
|
+
readonly type: "string";
|
|
635
|
+
readonly maxLength: 16;
|
|
636
|
+
};
|
|
637
|
+
readonly app_version: {
|
|
638
|
+
readonly type: "string";
|
|
639
|
+
};
|
|
640
|
+
readonly release_id: {
|
|
641
|
+
readonly type: "string";
|
|
642
|
+
readonly maxLength: 36;
|
|
643
|
+
};
|
|
644
|
+
readonly builtin_bundle_id: {
|
|
645
|
+
readonly type: "string";
|
|
646
|
+
readonly maxLength: 36;
|
|
647
|
+
};
|
|
648
|
+
readonly bucket_start_ms: {
|
|
649
|
+
readonly type: "integer";
|
|
650
|
+
};
|
|
651
|
+
}, "latest_installations", {
|
|
652
|
+
readonly byScope: {
|
|
653
|
+
readonly eq: readonly ["channel", "platform"];
|
|
654
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
655
|
+
};
|
|
656
|
+
readonly byVersion: {
|
|
657
|
+
readonly eq: readonly ["channel", "platform", "app_version"];
|
|
658
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
659
|
+
};
|
|
660
|
+
}, never, readonly ["channel", "platform", "app_version", "release_id", "builtin_bundle_id", "bucket_start_ms"]>;
|
|
597
661
|
readonly insights_latest_by_bundle: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
598
662
|
readonly platform: {
|
|
599
663
|
readonly type: "string";
|
package/dist/server/schema.d.mts
CHANGED
|
@@ -259,6 +259,38 @@ declare const createInsightsSchema: ({ rawDays, dailyDays }?: InsightsRetention)
|
|
|
259
259
|
readonly sort: readonly ["bucket_start_ms"];
|
|
260
260
|
};
|
|
261
261
|
}, never, readonly ["channel", "platform", "app_version", "release_id", "bucket_start_ms"]>;
|
|
262
|
+
readonly insights_builtin_distribution: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
263
|
+
readonly channel: {
|
|
264
|
+
readonly type: "string";
|
|
265
|
+
};
|
|
266
|
+
readonly platform: {
|
|
267
|
+
readonly type: "string";
|
|
268
|
+
readonly maxLength: 16;
|
|
269
|
+
};
|
|
270
|
+
readonly app_version: {
|
|
271
|
+
readonly type: "string";
|
|
272
|
+
};
|
|
273
|
+
readonly release_id: {
|
|
274
|
+
readonly type: "string";
|
|
275
|
+
readonly maxLength: 36;
|
|
276
|
+
};
|
|
277
|
+
readonly builtin_bundle_id: {
|
|
278
|
+
readonly type: "string";
|
|
279
|
+
readonly maxLength: 36;
|
|
280
|
+
};
|
|
281
|
+
readonly bucket_start_ms: {
|
|
282
|
+
readonly type: "integer";
|
|
283
|
+
};
|
|
284
|
+
}, "latest_installations", {
|
|
285
|
+
readonly byScope: {
|
|
286
|
+
readonly eq: readonly ["channel", "platform"];
|
|
287
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
288
|
+
};
|
|
289
|
+
readonly byVersion: {
|
|
290
|
+
readonly eq: readonly ["channel", "platform", "app_version"];
|
|
291
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
292
|
+
};
|
|
293
|
+
}, never, readonly ["channel", "platform", "app_version", "release_id", "builtin_bundle_id", "bucket_start_ms"]>;
|
|
262
294
|
readonly insights_latest_by_bundle: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
263
295
|
readonly platform: {
|
|
264
296
|
readonly type: "string";
|
|
@@ -594,6 +626,38 @@ declare const insightsSchema: {
|
|
|
594
626
|
readonly sort: readonly ["bucket_start_ms"];
|
|
595
627
|
};
|
|
596
628
|
}, never, readonly ["channel", "platform", "app_version", "release_id", "bucket_start_ms"]>;
|
|
629
|
+
readonly insights_builtin_distribution: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
630
|
+
readonly channel: {
|
|
631
|
+
readonly type: "string";
|
|
632
|
+
};
|
|
633
|
+
readonly platform: {
|
|
634
|
+
readonly type: "string";
|
|
635
|
+
readonly maxLength: 16;
|
|
636
|
+
};
|
|
637
|
+
readonly app_version: {
|
|
638
|
+
readonly type: "string";
|
|
639
|
+
};
|
|
640
|
+
readonly release_id: {
|
|
641
|
+
readonly type: "string";
|
|
642
|
+
readonly maxLength: 36;
|
|
643
|
+
};
|
|
644
|
+
readonly builtin_bundle_id: {
|
|
645
|
+
readonly type: "string";
|
|
646
|
+
readonly maxLength: 36;
|
|
647
|
+
};
|
|
648
|
+
readonly bucket_start_ms: {
|
|
649
|
+
readonly type: "integer";
|
|
650
|
+
};
|
|
651
|
+
}, "latest_installations", {
|
|
652
|
+
readonly byScope: {
|
|
653
|
+
readonly eq: readonly ["channel", "platform"];
|
|
654
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
655
|
+
};
|
|
656
|
+
readonly byVersion: {
|
|
657
|
+
readonly eq: readonly ["channel", "platform", "app_version"];
|
|
658
|
+
readonly sort: readonly ["bucket_start_ms"];
|
|
659
|
+
};
|
|
660
|
+
}, never, readonly ["channel", "platform", "app_version", "release_id", "builtin_bundle_id", "bucket_start_ms"]>;
|
|
597
661
|
readonly insights_latest_by_bundle: import("@hot-updater/plugin-core").AggregateDefinition<{
|
|
598
662
|
readonly platform: {
|
|
599
663
|
readonly type: "string";
|
package/dist/server/schema.mjs
CHANGED
|
@@ -354,6 +354,55 @@ const insightsDistribution = (retention) => defineAggregate({
|
|
|
354
354
|
},
|
|
355
355
|
retention
|
|
356
356
|
});
|
|
357
|
+
/**
|
|
358
|
+
* The installations of `insights_distribution` that run their native build's
|
|
359
|
+
* built-in bundle, by its ID (`builtin_bundle_id`), within the same rows:
|
|
360
|
+
* reads move them out of the row of their release, or of no release.
|
|
361
|
+
*/
|
|
362
|
+
const insightsBuiltinDistribution = (retention) => defineAggregate({
|
|
363
|
+
channel: { type: "string" },
|
|
364
|
+
platform: {
|
|
365
|
+
type: "string",
|
|
366
|
+
maxLength: 16
|
|
367
|
+
},
|
|
368
|
+
app_version: { type: "string" },
|
|
369
|
+
release_id: {
|
|
370
|
+
type: "string",
|
|
371
|
+
maxLength: 36
|
|
372
|
+
},
|
|
373
|
+
builtin_bundle_id: {
|
|
374
|
+
type: "string",
|
|
375
|
+
maxLength: 36
|
|
376
|
+
},
|
|
377
|
+
bucket_start_ms: { type: "integer" }
|
|
378
|
+
}, {
|
|
379
|
+
key: [
|
|
380
|
+
"channel",
|
|
381
|
+
"platform",
|
|
382
|
+
"app_version",
|
|
383
|
+
"release_id",
|
|
384
|
+
"builtin_bundle_id",
|
|
385
|
+
"bucket_start_ms"
|
|
386
|
+
],
|
|
387
|
+
gauges: ["latest_installations"],
|
|
388
|
+
shards: GAUGE_SHARDS,
|
|
389
|
+
batched: true,
|
|
390
|
+
indexes: {
|
|
391
|
+
byScope: {
|
|
392
|
+
eq: ["channel", "platform"],
|
|
393
|
+
sort: ["bucket_start_ms"]
|
|
394
|
+
},
|
|
395
|
+
byVersion: {
|
|
396
|
+
eq: [
|
|
397
|
+
"channel",
|
|
398
|
+
"platform",
|
|
399
|
+
"app_version"
|
|
400
|
+
],
|
|
401
|
+
sort: ["bucket_start_ms"]
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
retention
|
|
405
|
+
});
|
|
357
406
|
/** Latest events by the bundle they came from or went to, bucketed like the distribution. */
|
|
358
407
|
const insightsLatestByBundle = (retention) => defineAggregate({
|
|
359
408
|
platform: {
|
|
@@ -473,6 +522,7 @@ const createInsightsSchema = ({ rawDays, dailyDays } = DEFAULT_INSIGHTS_RETENTIO
|
|
|
473
522
|
insights_overview_lifetime: lifetimeCounters(),
|
|
474
523
|
insights_sketches_lifetime: lifetimeSketches(),
|
|
475
524
|
insights_distribution: insightsDistribution(daily),
|
|
525
|
+
insights_builtin_distribution: insightsBuiltinDistribution(daily),
|
|
476
526
|
insights_latest_by_bundle: insightsLatestByBundle(daily),
|
|
477
527
|
insights_outcomes: insightsOutcomes(hourly),
|
|
478
528
|
insights_failures: insightsFailures(hourly)
|
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.36",
|
|
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": {
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"package.json"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@hot-updater/protocol": "1.0.0-rc.
|
|
36
|
+
"@hot-updater/protocol": "1.0.0-rc.36"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@hot-updater/plugin-core": "^1.0.0-rc.
|
|
39
|
+
"@hot-updater/plugin-core": "^1.0.0-rc.36"
|
|
40
40
|
},
|
|
41
41
|
"peerDependenciesMeta": {
|
|
42
42
|
"@hot-updater/plugin-core": {
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^20",
|
|
48
48
|
"vitest": "4.1.4",
|
|
49
|
-
"@hot-updater/plugin-core": "1.0.0-rc.
|
|
50
|
-
"@hot-updater/test-utils": "1.0.0-rc.
|
|
49
|
+
"@hot-updater/plugin-core": "1.0.0-rc.36",
|
|
50
|
+
"@hot-updater/test-utils": "1.0.0-rc.36"
|
|
51
51
|
},
|
|
52
52
|
"nx": {
|
|
53
53
|
"implicitDependencies": [
|