@hot-updater/plugin-insights 1.0.0-rc.35 → 1.0.0-rc.37
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/contract.cjs +8 -4
- package/dist/server/contract.mjs +8 -4
- package/dist/server/domain.d.cts +40 -4
- package/dist/server/domain.d.mts +40 -4
- package/dist/server/eventInput.cjs +7 -0
- package/dist/server/eventInput.mjs +7 -0
- package/dist/server/eventRow.cjs +24 -2
- package/dist/server/eventRow.d.cts +35 -1
- package/dist/server/eventRow.d.mts +35 -1
- package/dist/server/eventRow.mjs +24 -3
- package/dist/server/index.cjs +1 -1
- package/dist/server/index.d.cts +34 -2
- package/dist/server/index.d.mts +34 -2
- package/dist/server/index.mjs +1 -1
- package/dist/server/modelTypes.d.cts +6 -2
- package/dist/server/modelTypes.d.mts +6 -2
- package/dist/server/overview.cjs +7 -5
- package/dist/server/overview.d.cts +3 -3
- package/dist/server/overview.d.mts +3 -3
- package/dist/server/overview.mjs +7 -5
- package/dist/server/provider.cjs +15 -1
- package/dist/server/provider.mjs +15 -1
- package/dist/server/reads.cjs +60 -29
- package/dist/server/reads.mjs +60 -29
- package/dist/server/recordEvent.cjs +156 -22
- package/dist/server/recordEvent.mjs +157 -23
- package/dist/server/schema.cjs +96 -10
- package/dist/server/schema.d.cts +64 -0
- package/dist/server/schema.d.mts +64 -0
- package/dist/server/schema.mjs +93 -11
- 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/contract.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_eventRow = require("./eventRow.cjs");
|
|
2
|
+
const require_schema = require("./schema.cjs");
|
|
2
3
|
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
3
4
|
//#region src/server/contract.ts
|
|
4
5
|
const encoder = new TextEncoder();
|
|
@@ -30,7 +31,7 @@ const isBundleFilter = (value, withKind = false) => {
|
|
|
30
31
|
"type",
|
|
31
32
|
...withKind ? ["kind"] : []
|
|
32
33
|
];
|
|
33
|
-
return value.type === "RECOVERED" ? isText(value.fromBundleId) && hasOnlyKeys(value, [...keys, "fromBundleId"]) : (value.type === "UPDATE_DOWNLOADED" || value.type === "UPDATE_APPLIED" || value.type === "UPDATE_FAILED") && isText(value.toBundleId) && hasOnlyKeys(value, [...keys, "toBundleId"]);
|
|
34
|
+
return value.type === "RECOVERED" ? isText(value.fromBundleId) && hasOnlyKeys(value, [...keys, "fromBundleId"]) : (value.type === "UPDATE_DOWNLOADED" || value.type === "UPDATE_APPLIED" || value.type === "UPDATE_FAILED" || value.type === "UNCHANGED") && isText(value.toBundleId) && hasOnlyKeys(value, [...keys, "toBundleId"]);
|
|
34
35
|
};
|
|
35
36
|
const isEventFilter = (value) => {
|
|
36
37
|
if (!require_eventRow.isRecord(value)) return false;
|
|
@@ -49,12 +50,15 @@ const validateRow = (model, row, result = false) => {
|
|
|
49
50
|
};
|
|
50
51
|
/** Throws `invalid-data` unless `row` is a complete, well-formed bundle event row. */
|
|
51
52
|
const assertBundleEventRow = (row) => validateRow("bundle_events", row);
|
|
52
|
-
/**
|
|
53
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Downloads, applies, recoveries, failed updates, and the UNCHANGED rows
|
|
55
|
+
* kept for a change belong in installation history.
|
|
56
|
+
*/
|
|
57
|
+
const isInsightsMovementEvent = (event) => event.type === "UPDATE_DOWNLOADED" || event.type === "UPDATE_APPLIED" || event.type === "RECOVERED" || event.type === "UPDATE_FAILED" || event.type === "UNCHANGED";
|
|
54
58
|
const matchesInsightsEventFilter = (event, filter) => {
|
|
55
59
|
if (filter.kind === "all") return true;
|
|
56
60
|
if (filter.kind === "installationMovement") return event.install_id === filter.installId && isInsightsMovementEvent(event);
|
|
57
|
-
return event.type === filter.type && event.platform === filter.platform && event.channel === filter.channel && (
|
|
61
|
+
return event.type === filter.type && event.platform === filter.platform && event.channel === filter.channel && require_schema.bundleRefsOf(event).includes(require_schema.bundleRefOfFilter(filter));
|
|
58
62
|
};
|
|
59
63
|
const invalidQuery = () => {
|
|
60
64
|
throw new _hot_updater_plugin_core.DatabaseAdapterInputError("invalid-query");
|
package/dist/server/contract.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isRecord, validateBundleEventFields } from "./eventRow.mjs";
|
|
2
|
+
import { bundleRefOfFilter, bundleRefsOf } from "./schema.mjs";
|
|
2
3
|
import { DatabaseAdapterInputError, isUUIDv7 } from "@hot-updater/plugin-core";
|
|
3
4
|
//#region src/server/contract.ts
|
|
4
5
|
const encoder = new TextEncoder();
|
|
@@ -30,7 +31,7 @@ const isBundleFilter = (value, withKind = false) => {
|
|
|
30
31
|
"type",
|
|
31
32
|
...withKind ? ["kind"] : []
|
|
32
33
|
];
|
|
33
|
-
return value.type === "RECOVERED" ? isText(value.fromBundleId) && hasOnlyKeys(value, [...keys, "fromBundleId"]) : (value.type === "UPDATE_DOWNLOADED" || value.type === "UPDATE_APPLIED" || value.type === "UPDATE_FAILED") && isText(value.toBundleId) && hasOnlyKeys(value, [...keys, "toBundleId"]);
|
|
34
|
+
return value.type === "RECOVERED" ? isText(value.fromBundleId) && hasOnlyKeys(value, [...keys, "fromBundleId"]) : (value.type === "UPDATE_DOWNLOADED" || value.type === "UPDATE_APPLIED" || value.type === "UPDATE_FAILED" || value.type === "UNCHANGED") && isText(value.toBundleId) && hasOnlyKeys(value, [...keys, "toBundleId"]);
|
|
34
35
|
};
|
|
35
36
|
const isEventFilter = (value) => {
|
|
36
37
|
if (!isRecord(value)) return false;
|
|
@@ -49,12 +50,15 @@ const validateRow = (model, row, result = false) => {
|
|
|
49
50
|
};
|
|
50
51
|
/** Throws `invalid-data` unless `row` is a complete, well-formed bundle event row. */
|
|
51
52
|
const assertBundleEventRow = (row) => validateRow("bundle_events", row);
|
|
52
|
-
/**
|
|
53
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Downloads, applies, recoveries, failed updates, and the UNCHANGED rows
|
|
55
|
+
* kept for a change belong in installation history.
|
|
56
|
+
*/
|
|
57
|
+
const isInsightsMovementEvent = (event) => event.type === "UPDATE_DOWNLOADED" || event.type === "UPDATE_APPLIED" || event.type === "RECOVERED" || event.type === "UPDATE_FAILED" || event.type === "UNCHANGED";
|
|
54
58
|
const matchesInsightsEventFilter = (event, filter) => {
|
|
55
59
|
if (filter.kind === "all") return true;
|
|
56
60
|
if (filter.kind === "installationMovement") return event.install_id === filter.installId && isInsightsMovementEvent(event);
|
|
57
|
-
return event.type === filter.type && event.platform === filter.platform && event.channel === filter.channel && (
|
|
61
|
+
return event.type === filter.type && event.platform === filter.platform && event.channel === filter.channel && bundleRefsOf(event).includes(bundleRefOfFilter(filter));
|
|
58
62
|
};
|
|
59
63
|
const invalidQuery = () => {
|
|
60
64
|
throw new DatabaseAdapterInputError("invalid-query");
|
package/dist/server/domain.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BundleEventFailure, BundleEventFailureReason, BundleEventFailureStage, DatabaseBundleEventMetadata } from "./eventRow.cjs";
|
|
1
|
+
import { BundleEventChangeKind, BundleEventFailure, BundleEventFailureReason, BundleEventFailureStage, DatabaseBundleEventMetadata } from "./eventRow.cjs";
|
|
2
2
|
import { InsightsScope } from "./modelTypes.cjs";
|
|
3
3
|
import { UpdateHttpResponse } from "@hot-updater/protocol";
|
|
4
4
|
//#region src/server/domain.d.ts
|
|
@@ -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
|
};
|
|
@@ -76,9 +82,27 @@ type CreateBundleEventRequest = (Movement & {
|
|
|
76
82
|
readonly updateStrategy: null;
|
|
77
83
|
});
|
|
78
84
|
type ActiveInstallationWindow = "24h" | "7d" | "30d";
|
|
85
|
+
/**
|
|
86
|
+
* What a kept UNCHANGED report changed against its installation's previous
|
|
87
|
+
* report: the running bundle or release, the app version, or the channel,
|
|
88
|
+
* with the previous values; `first_seen` alone for an installation's first
|
|
89
|
+
* report to this server.
|
|
90
|
+
*/
|
|
91
|
+
type EventHistoryChange = {
|
|
92
|
+
readonly kinds: readonly BundleEventChangeKind[];
|
|
93
|
+
readonly previous?: {
|
|
94
|
+
readonly bundleId: string;
|
|
95
|
+
readonly releaseId: string | null;
|
|
96
|
+
readonly appVersion: string;
|
|
97
|
+
readonly channel: string;
|
|
98
|
+
readonly minBundleId?: string;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
79
101
|
type EventHistoryRow = {
|
|
80
102
|
readonly toReleaseId?: string;
|
|
81
103
|
readonly sdkVersion?: string;
|
|
104
|
+
/** The native build's built-in bundle ID, when the SDK reported it. */
|
|
105
|
+
readonly minBundleId?: string;
|
|
82
106
|
readonly id: string;
|
|
83
107
|
readonly installId: string;
|
|
84
108
|
readonly type: "UPDATE_DOWNLOADED" | "UPDATE_APPLIED" | "RECOVERED" | "UPDATE_FAILED" | "UNCHANGED";
|
|
@@ -97,16 +121,28 @@ type EventHistoryRow = {
|
|
|
97
121
|
readonly delivery?: NonNullable<DatabaseBundleEventMetadata["delivery"]>;
|
|
98
122
|
/** `UPDATE_DOWNLOADED`: a patch failed, and the files or the archive came instead. */
|
|
99
123
|
readonly patchFallback?: true;
|
|
124
|
+
/** `UNCHANGED`: what the report changed, the reason it was kept. */
|
|
125
|
+
readonly change?: EventHistoryChange;
|
|
126
|
+
/** A download or apply that arrived after its target already ran: it counted nothing. */
|
|
127
|
+
readonly late?: true;
|
|
128
|
+
/** A launch or crash whose download report never arrived, counted with it. */
|
|
129
|
+
readonly impliedDownload?: true;
|
|
100
130
|
};
|
|
101
|
-
type InstallationHistoryRow = EventHistoryRow & {
|
|
131
|
+
type InstallationHistoryRow = EventHistoryRow & ({
|
|
102
132
|
readonly type: "UPDATE_DOWNLOADED" | "UPDATE_APPLIED" | "RECOVERED" | "UPDATE_FAILED";
|
|
103
133
|
readonly fromBundleId: string;
|
|
104
|
-
}
|
|
134
|
+
} | {
|
|
135
|
+
readonly type: "UNCHANGED";
|
|
136
|
+
readonly fromBundleId: null;
|
|
137
|
+
readonly change: EventHistoryChange;
|
|
138
|
+
});
|
|
105
139
|
type InsightsHttpResponse = UpdateHttpResponse & {
|
|
106
140
|
readonly receivedAtMs: number;
|
|
107
141
|
};
|
|
108
142
|
type InstallationRow = {
|
|
109
143
|
readonly httpResponse?: InsightsHttpResponse;
|
|
144
|
+
/** The native build's built-in bundle ID, when the SDK reported it. */
|
|
145
|
+
readonly minBundleId?: string;
|
|
110
146
|
readonly installId: string;
|
|
111
147
|
readonly userId: string | null;
|
|
112
148
|
readonly lastKnownBundleId: string;
|
|
@@ -150,4 +186,4 @@ type ReportingOverview = InsightsScope & {
|
|
|
150
186
|
};
|
|
151
187
|
};
|
|
152
188
|
//#endregion
|
|
153
|
-
export { ActiveInstallationWindow, BundleEventFailureInput, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsHttpResponse, InstallationHistoryRow, InstallationRow, ReportingOverview };
|
|
189
|
+
export { ActiveInstallationWindow, BundleEventFailureInput, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryChange, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsHttpResponse, InstallationHistoryRow, InstallationRow, ReportingOverview };
|
package/dist/server/domain.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BundleEventFailure, BundleEventFailureReason, BundleEventFailureStage, DatabaseBundleEventMetadata } from "./eventRow.mjs";
|
|
1
|
+
import { BundleEventChangeKind, BundleEventFailure, BundleEventFailureReason, BundleEventFailureStage, DatabaseBundleEventMetadata } from "./eventRow.mjs";
|
|
2
2
|
import { InsightsScope } from "./modelTypes.mjs";
|
|
3
3
|
import { UpdateHttpResponse } from "@hot-updater/protocol";
|
|
4
4
|
//#region src/server/domain.d.ts
|
|
@@ -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
|
};
|
|
@@ -76,9 +82,27 @@ type CreateBundleEventRequest = (Movement & {
|
|
|
76
82
|
readonly updateStrategy: null;
|
|
77
83
|
});
|
|
78
84
|
type ActiveInstallationWindow = "24h" | "7d" | "30d";
|
|
85
|
+
/**
|
|
86
|
+
* What a kept UNCHANGED report changed against its installation's previous
|
|
87
|
+
* report: the running bundle or release, the app version, or the channel,
|
|
88
|
+
* with the previous values; `first_seen` alone for an installation's first
|
|
89
|
+
* report to this server.
|
|
90
|
+
*/
|
|
91
|
+
type EventHistoryChange = {
|
|
92
|
+
readonly kinds: readonly BundleEventChangeKind[];
|
|
93
|
+
readonly previous?: {
|
|
94
|
+
readonly bundleId: string;
|
|
95
|
+
readonly releaseId: string | null;
|
|
96
|
+
readonly appVersion: string;
|
|
97
|
+
readonly channel: string;
|
|
98
|
+
readonly minBundleId?: string;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
79
101
|
type EventHistoryRow = {
|
|
80
102
|
readonly toReleaseId?: string;
|
|
81
103
|
readonly sdkVersion?: string;
|
|
104
|
+
/** The native build's built-in bundle ID, when the SDK reported it. */
|
|
105
|
+
readonly minBundleId?: string;
|
|
82
106
|
readonly id: string;
|
|
83
107
|
readonly installId: string;
|
|
84
108
|
readonly type: "UPDATE_DOWNLOADED" | "UPDATE_APPLIED" | "RECOVERED" | "UPDATE_FAILED" | "UNCHANGED";
|
|
@@ -97,16 +121,28 @@ type EventHistoryRow = {
|
|
|
97
121
|
readonly delivery?: NonNullable<DatabaseBundleEventMetadata["delivery"]>;
|
|
98
122
|
/** `UPDATE_DOWNLOADED`: a patch failed, and the files or the archive came instead. */
|
|
99
123
|
readonly patchFallback?: true;
|
|
124
|
+
/** `UNCHANGED`: what the report changed, the reason it was kept. */
|
|
125
|
+
readonly change?: EventHistoryChange;
|
|
126
|
+
/** A download or apply that arrived after its target already ran: it counted nothing. */
|
|
127
|
+
readonly late?: true;
|
|
128
|
+
/** A launch or crash whose download report never arrived, counted with it. */
|
|
129
|
+
readonly impliedDownload?: true;
|
|
100
130
|
};
|
|
101
|
-
type InstallationHistoryRow = EventHistoryRow & {
|
|
131
|
+
type InstallationHistoryRow = EventHistoryRow & ({
|
|
102
132
|
readonly type: "UPDATE_DOWNLOADED" | "UPDATE_APPLIED" | "RECOVERED" | "UPDATE_FAILED";
|
|
103
133
|
readonly fromBundleId: string;
|
|
104
|
-
}
|
|
134
|
+
} | {
|
|
135
|
+
readonly type: "UNCHANGED";
|
|
136
|
+
readonly fromBundleId: null;
|
|
137
|
+
readonly change: EventHistoryChange;
|
|
138
|
+
});
|
|
105
139
|
type InsightsHttpResponse = UpdateHttpResponse & {
|
|
106
140
|
readonly receivedAtMs: number;
|
|
107
141
|
};
|
|
108
142
|
type InstallationRow = {
|
|
109
143
|
readonly httpResponse?: InsightsHttpResponse;
|
|
144
|
+
/** The native build's built-in bundle ID, when the SDK reported it. */
|
|
145
|
+
readonly minBundleId?: string;
|
|
110
146
|
readonly installId: string;
|
|
111
147
|
readonly userId: string | null;
|
|
112
148
|
readonly lastKnownBundleId: string;
|
|
@@ -150,4 +186,4 @@ type ReportingOverview = InsightsScope & {
|
|
|
150
186
|
};
|
|
151
187
|
};
|
|
152
188
|
//#endregion
|
|
153
|
-
export { ActiveInstallationWindow, BundleEventFailureInput, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsHttpResponse, InstallationHistoryRow, InstallationRow, ReportingOverview };
|
|
189
|
+
export { ActiveInstallationWindow, BundleEventFailureInput, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryChange, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsHttpResponse, InstallationHistoryRow, InstallationRow, ReportingOverview };
|
|
@@ -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
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
2
2
|
//#region src/server/eventRow.ts
|
|
3
|
+
const CHANGE_KINDS = /* @__PURE__ */ new Set([
|
|
4
|
+
"first_seen",
|
|
5
|
+
"bundle",
|
|
6
|
+
"release",
|
|
7
|
+
"app_version",
|
|
8
|
+
"channel",
|
|
9
|
+
"native_build"
|
|
10
|
+
]);
|
|
11
|
+
const isBundleEventChange = (value) => (0, _hot_updater_plugin_core.isDatabaseJsonObject)(value) && Array.isArray(value.kinds) && value.kinds.length > 0 && value.kinds.every((kind) => CHANGE_KINDS.has(kind)) && (value.previous === null || (0, _hot_updater_plugin_core.isDatabaseJsonObject)(value.previous) && typeof value.previous.bundle_id === "string" && (value.previous.release_id === null || typeof value.previous.release_id === "string") && typeof value.previous.app_version === "string" && typeof value.previous.channel === "string" && isOptional(value.previous, "min_bundle_id", isString));
|
|
3
12
|
const isOptional = (value, key, valid) => !Object.hasOwn(value, key) || valid(value[key]);
|
|
4
13
|
const isString = (value) => typeof value === "string";
|
|
5
14
|
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
15
|
/** An `UPDATE_FAILED` report's stored failure: a stage and a reason, and what else the client knew. */
|
|
7
16
|
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");
|
|
17
|
+
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") && isOptional(value, "change", isBundleEventChange) && isOptional(value, "late", (flag) => flag === true) && isOptional(value, "implied_download", (flag) => flag === true);
|
|
9
18
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19
|
+
/**
|
|
20
|
+
* The built-in bundle a report says its installation runs: the running
|
|
21
|
+
* bundle, which a download leaves at its source, when it is the native
|
|
22
|
+
* build's built-in bundle, whatever Release selected it. Null for any other
|
|
23
|
+
* bundle, and for a report without the build's built-in bundle ID.
|
|
24
|
+
*/
|
|
25
|
+
const runningBuiltinBundleId = (row) => {
|
|
26
|
+
const running = row.type === "UPDATE_DOWNLOADED" ? row.from_bundle_id : row.to_bundle_id;
|
|
27
|
+
const builtin = isRecord(row.metadata) ? row.metadata.min_bundle_id : null;
|
|
28
|
+
return typeof builtin === "string" && running === builtin ? builtin : null;
|
|
29
|
+
};
|
|
10
30
|
const isIdentity = (value) => typeof value === "string" && value.length > 0 && value.length <= 255;
|
|
11
31
|
const isTextOrNull = (value) => value === null || typeof value === "string";
|
|
12
32
|
/** Each bundle event field and what it holds. */
|
|
@@ -25,13 +45,14 @@ const BUNDLE_EVENT_FIELDS = {
|
|
|
25
45
|
metadata: isDatabaseBundleEventMetadata,
|
|
26
46
|
received_at_ms: (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0
|
|
27
47
|
};
|
|
48
|
+
const hasMetadata = (row, key) => isRecord(row.metadata) && Object.hasOwn(row.metadata, key);
|
|
28
49
|
const updateStrategyOf = (row) => isRecord(row.metadata) ? row.metadata.update_strategy : void 0;
|
|
29
50
|
/**
|
|
30
51
|
* A movement, or a failed update, names the bundle it left and how the
|
|
31
52
|
* device updates, and a failed update says what failed; an unchanged report
|
|
32
53
|
* names neither.
|
|
33
54
|
*/
|
|
34
|
-
const hasEventInvariants = (row) => (row.type === "UPDATE_DOWNLOADED" || row.type === "UPDATE_APPLIED" || row.type === "RECOVERED" || row.type === "UPDATE_FAILED") && typeof row.from_bundle_id === "string" && (updateStrategyOf(row) === "fingerprint" || updateStrategyOf(row) === "appVersion") && (row.type !== "UPDATE_FAILED" || isRecord(row.metadata) && isRecord(row.metadata.failure)) || row.type === "UNCHANGED" && row.from_bundle_id === null && updateStrategyOf(row) === null;
|
|
55
|
+
const hasEventInvariants = (row) => (row.type === "UPDATE_DOWNLOADED" || row.type === "UPDATE_APPLIED" || row.type === "RECOVERED" || row.type === "UPDATE_FAILED") && typeof row.from_bundle_id === "string" && (updateStrategyOf(row) === "fingerprint" || updateStrategyOf(row) === "appVersion") && (row.type !== "UPDATE_FAILED" || isRecord(row.metadata) && isRecord(row.metadata.failure)) && !hasMetadata(row, "change") && (!hasMetadata(row, "late") || row.type === "UPDATE_DOWNLOADED" || row.type === "UPDATE_APPLIED") && (!hasMetadata(row, "implied_download") || row.type === "UPDATE_APPLIED" || row.type === "RECOVERED") || row.type === "UNCHANGED" && !hasMetadata(row, "late") && row.from_bundle_id === null && updateStrategyOf(row) === null;
|
|
35
56
|
/**
|
|
36
57
|
* Throws unless `row` has exactly the bundle event fields, each of its type,
|
|
37
58
|
* and the invariants of its event type: `invalid-field` for an unknown field,
|
|
@@ -46,4 +67,5 @@ const validateBundleEventFields = (row) => {
|
|
|
46
67
|
//#endregion
|
|
47
68
|
exports.isDatabaseBundleEventMetadata = isDatabaseBundleEventMetadata;
|
|
48
69
|
exports.isRecord = isRecord;
|
|
70
|
+
exports.runningBuiltinBundleId = runningBuiltinBundleId;
|
|
49
71
|
exports.validateBundleEventFields = validateBundleEventFields;
|
|
@@ -25,12 +25,33 @@ type DatabaseHttpResponse = DatabaseJsonObject & {
|
|
|
25
25
|
readonly body_truncated: boolean;
|
|
26
26
|
readonly received_at_ms: number;
|
|
27
27
|
};
|
|
28
|
+
/** What a kept UNCHANGED row changed against its installation's head. */
|
|
29
|
+
type BundleEventChangeKind = "first_seen" | "bundle" | "release" | "app_version" | "channel" | "native_build";
|
|
30
|
+
/**
|
|
31
|
+
* An UNCHANGED report the server keeps: what it changed against its
|
|
32
|
+
* installation's head, and the running values the head held before it. A
|
|
33
|
+
* report from an installation without a head is `first_seen` alone, with no
|
|
34
|
+
* previous values: the installation is new to this server, not necessarily
|
|
35
|
+
* to its device.
|
|
36
|
+
*/
|
|
37
|
+
type BundleEventChange = DatabaseJsonObject & {
|
|
38
|
+
readonly kinds: BundleEventChangeKind[];
|
|
39
|
+
readonly previous: (DatabaseJsonObject & {
|
|
40
|
+
readonly bundle_id: string;
|
|
41
|
+
readonly release_id: string | null;
|
|
42
|
+
readonly app_version: string;
|
|
43
|
+
readonly channel: string;
|
|
44
|
+
readonly min_bundle_id?: string;
|
|
45
|
+
}) | null;
|
|
46
|
+
};
|
|
28
47
|
/** Ancillary report data; queryable identity and lifecycle fields stay on the row. */
|
|
29
48
|
type DatabaseBundleEventMetadata = DatabaseJsonObject & {
|
|
30
49
|
readonly cohort: string;
|
|
31
50
|
readonly update_strategy: "fingerprint" | "appVersion" | null;
|
|
32
51
|
readonly fingerprint_hash: string | null;
|
|
33
52
|
readonly sdk_version: string | null;
|
|
53
|
+
/** The native build's built-in bundle ID, when the SDK reports it. */
|
|
54
|
+
readonly min_bundle_id?: string;
|
|
34
55
|
/** `UPDATE_FAILED`: what failed. */
|
|
35
56
|
readonly failure?: BundleEventFailure;
|
|
36
57
|
readonly http_response?: DatabaseHttpResponse;
|
|
@@ -38,6 +59,19 @@ type DatabaseBundleEventMetadata = DatabaseJsonObject & {
|
|
|
38
59
|
readonly delivery?: "patch" | "manifest" | "archive" | "unknown";
|
|
39
60
|
/** `UPDATE_DOWNLOADED`: a patch failed and the full files came instead. */
|
|
40
61
|
readonly patch_fallback?: boolean;
|
|
62
|
+
/** A kept `UNCHANGED` row: what it changed, which the server sets. */
|
|
63
|
+
readonly change?: BundleEventChange;
|
|
64
|
+
/**
|
|
65
|
+
* A download or apply that arrived after its installation already ran its
|
|
66
|
+
* target, as when a reload cut the first runtime's report short: the
|
|
67
|
+
* server keeps it in history, but it moves and counts nothing.
|
|
68
|
+
*/
|
|
69
|
+
readonly late?: true;
|
|
70
|
+
/**
|
|
71
|
+
* A launch or crash of a bundle whose download report never arrived: the
|
|
72
|
+
* server counted that download with it.
|
|
73
|
+
*/
|
|
74
|
+
readonly implied_download?: true;
|
|
41
75
|
};
|
|
42
76
|
type BundleEventRowBase = {
|
|
43
77
|
readonly id: string;
|
|
@@ -68,4 +102,4 @@ type BundleEventRow = BundleEventRowBase & ({
|
|
|
68
102
|
readonly from_bundle_id: null;
|
|
69
103
|
});
|
|
70
104
|
//#endregion
|
|
71
|
-
export { BundleEventFailure, BundleEventFailureReason, BundleEventFailureStage, BundleEventRow, BundleEventRowBase, DatabaseBundleEventMetadata, DatabaseHttpResponse };
|
|
105
|
+
export { BundleEventChange, BundleEventChangeKind, BundleEventFailure, BundleEventFailureReason, BundleEventFailureStage, BundleEventRow, BundleEventRowBase, DatabaseBundleEventMetadata, DatabaseHttpResponse };
|
|
@@ -25,12 +25,33 @@ type DatabaseHttpResponse = DatabaseJsonObject & {
|
|
|
25
25
|
readonly body_truncated: boolean;
|
|
26
26
|
readonly received_at_ms: number;
|
|
27
27
|
};
|
|
28
|
+
/** What a kept UNCHANGED row changed against its installation's head. */
|
|
29
|
+
type BundleEventChangeKind = "first_seen" | "bundle" | "release" | "app_version" | "channel" | "native_build";
|
|
30
|
+
/**
|
|
31
|
+
* An UNCHANGED report the server keeps: what it changed against its
|
|
32
|
+
* installation's head, and the running values the head held before it. A
|
|
33
|
+
* report from an installation without a head is `first_seen` alone, with no
|
|
34
|
+
* previous values: the installation is new to this server, not necessarily
|
|
35
|
+
* to its device.
|
|
36
|
+
*/
|
|
37
|
+
type BundleEventChange = DatabaseJsonObject & {
|
|
38
|
+
readonly kinds: BundleEventChangeKind[];
|
|
39
|
+
readonly previous: (DatabaseJsonObject & {
|
|
40
|
+
readonly bundle_id: string;
|
|
41
|
+
readonly release_id: string | null;
|
|
42
|
+
readonly app_version: string;
|
|
43
|
+
readonly channel: string;
|
|
44
|
+
readonly min_bundle_id?: string;
|
|
45
|
+
}) | null;
|
|
46
|
+
};
|
|
28
47
|
/** Ancillary report data; queryable identity and lifecycle fields stay on the row. */
|
|
29
48
|
type DatabaseBundleEventMetadata = DatabaseJsonObject & {
|
|
30
49
|
readonly cohort: string;
|
|
31
50
|
readonly update_strategy: "fingerprint" | "appVersion" | null;
|
|
32
51
|
readonly fingerprint_hash: string | null;
|
|
33
52
|
readonly sdk_version: string | null;
|
|
53
|
+
/** The native build's built-in bundle ID, when the SDK reports it. */
|
|
54
|
+
readonly min_bundle_id?: string;
|
|
34
55
|
/** `UPDATE_FAILED`: what failed. */
|
|
35
56
|
readonly failure?: BundleEventFailure;
|
|
36
57
|
readonly http_response?: DatabaseHttpResponse;
|
|
@@ -38,6 +59,19 @@ type DatabaseBundleEventMetadata = DatabaseJsonObject & {
|
|
|
38
59
|
readonly delivery?: "patch" | "manifest" | "archive" | "unknown";
|
|
39
60
|
/** `UPDATE_DOWNLOADED`: a patch failed and the full files came instead. */
|
|
40
61
|
readonly patch_fallback?: boolean;
|
|
62
|
+
/** A kept `UNCHANGED` row: what it changed, which the server sets. */
|
|
63
|
+
readonly change?: BundleEventChange;
|
|
64
|
+
/**
|
|
65
|
+
* A download or apply that arrived after its installation already ran its
|
|
66
|
+
* target, as when a reload cut the first runtime's report short: the
|
|
67
|
+
* server keeps it in history, but it moves and counts nothing.
|
|
68
|
+
*/
|
|
69
|
+
readonly late?: true;
|
|
70
|
+
/**
|
|
71
|
+
* A launch or crash of a bundle whose download report never arrived: the
|
|
72
|
+
* server counted that download with it.
|
|
73
|
+
*/
|
|
74
|
+
readonly implied_download?: true;
|
|
41
75
|
};
|
|
42
76
|
type BundleEventRowBase = {
|
|
43
77
|
readonly id: string;
|
|
@@ -68,4 +102,4 @@ type BundleEventRow = BundleEventRowBase & ({
|
|
|
68
102
|
readonly from_bundle_id: null;
|
|
69
103
|
});
|
|
70
104
|
//#endregion
|
|
71
|
-
export { BundleEventFailure, BundleEventFailureReason, BundleEventFailureStage, BundleEventRow, BundleEventRowBase, DatabaseBundleEventMetadata, DatabaseHttpResponse };
|
|
105
|
+
export { BundleEventChange, BundleEventChangeKind, BundleEventFailure, BundleEventFailureReason, BundleEventFailureStage, BundleEventRow, BundleEventRowBase, DatabaseBundleEventMetadata, DatabaseHttpResponse };
|
package/dist/server/eventRow.mjs
CHANGED
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
import { DatabaseAdapterInputError, isDatabaseJsonObject } from "@hot-updater/plugin-core";
|
|
2
2
|
//#region src/server/eventRow.ts
|
|
3
|
+
const CHANGE_KINDS = /* @__PURE__ */ new Set([
|
|
4
|
+
"first_seen",
|
|
5
|
+
"bundle",
|
|
6
|
+
"release",
|
|
7
|
+
"app_version",
|
|
8
|
+
"channel",
|
|
9
|
+
"native_build"
|
|
10
|
+
]);
|
|
11
|
+
const isBundleEventChange = (value) => isDatabaseJsonObject(value) && Array.isArray(value.kinds) && value.kinds.length > 0 && value.kinds.every((kind) => CHANGE_KINDS.has(kind)) && (value.previous === null || isDatabaseJsonObject(value.previous) && typeof value.previous.bundle_id === "string" && (value.previous.release_id === null || typeof value.previous.release_id === "string") && typeof value.previous.app_version === "string" && typeof value.previous.channel === "string" && isOptional(value.previous, "min_bundle_id", isString));
|
|
3
12
|
const isOptional = (value, key, valid) => !Object.hasOwn(value, key) || valid(value[key]);
|
|
4
13
|
const isString = (value) => typeof value === "string";
|
|
5
14
|
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
15
|
/** An `UPDATE_FAILED` report's stored failure: a stage and a reason, and what else the client knew. */
|
|
7
16
|
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");
|
|
17
|
+
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") && isOptional(value, "change", isBundleEventChange) && isOptional(value, "late", (flag) => flag === true) && isOptional(value, "implied_download", (flag) => flag === true);
|
|
9
18
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19
|
+
/**
|
|
20
|
+
* The built-in bundle a report says its installation runs: the running
|
|
21
|
+
* bundle, which a download leaves at its source, when it is the native
|
|
22
|
+
* build's built-in bundle, whatever Release selected it. Null for any other
|
|
23
|
+
* bundle, and for a report without the build's built-in bundle ID.
|
|
24
|
+
*/
|
|
25
|
+
const runningBuiltinBundleId = (row) => {
|
|
26
|
+
const running = row.type === "UPDATE_DOWNLOADED" ? row.from_bundle_id : row.to_bundle_id;
|
|
27
|
+
const builtin = isRecord(row.metadata) ? row.metadata.min_bundle_id : null;
|
|
28
|
+
return typeof builtin === "string" && running === builtin ? builtin : null;
|
|
29
|
+
};
|
|
10
30
|
const isIdentity = (value) => typeof value === "string" && value.length > 0 && value.length <= 255;
|
|
11
31
|
const isTextOrNull = (value) => value === null || typeof value === "string";
|
|
12
32
|
/** Each bundle event field and what it holds. */
|
|
@@ -25,13 +45,14 @@ const BUNDLE_EVENT_FIELDS = {
|
|
|
25
45
|
metadata: isDatabaseBundleEventMetadata,
|
|
26
46
|
received_at_ms: (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0
|
|
27
47
|
};
|
|
48
|
+
const hasMetadata = (row, key) => isRecord(row.metadata) && Object.hasOwn(row.metadata, key);
|
|
28
49
|
const updateStrategyOf = (row) => isRecord(row.metadata) ? row.metadata.update_strategy : void 0;
|
|
29
50
|
/**
|
|
30
51
|
* A movement, or a failed update, names the bundle it left and how the
|
|
31
52
|
* device updates, and a failed update says what failed; an unchanged report
|
|
32
53
|
* names neither.
|
|
33
54
|
*/
|
|
34
|
-
const hasEventInvariants = (row) => (row.type === "UPDATE_DOWNLOADED" || row.type === "UPDATE_APPLIED" || row.type === "RECOVERED" || row.type === "UPDATE_FAILED") && typeof row.from_bundle_id === "string" && (updateStrategyOf(row) === "fingerprint" || updateStrategyOf(row) === "appVersion") && (row.type !== "UPDATE_FAILED" || isRecord(row.metadata) && isRecord(row.metadata.failure)) || row.type === "UNCHANGED" && row.from_bundle_id === null && updateStrategyOf(row) === null;
|
|
55
|
+
const hasEventInvariants = (row) => (row.type === "UPDATE_DOWNLOADED" || row.type === "UPDATE_APPLIED" || row.type === "RECOVERED" || row.type === "UPDATE_FAILED") && typeof row.from_bundle_id === "string" && (updateStrategyOf(row) === "fingerprint" || updateStrategyOf(row) === "appVersion") && (row.type !== "UPDATE_FAILED" || isRecord(row.metadata) && isRecord(row.metadata.failure)) && !hasMetadata(row, "change") && (!hasMetadata(row, "late") || row.type === "UPDATE_DOWNLOADED" || row.type === "UPDATE_APPLIED") && (!hasMetadata(row, "implied_download") || row.type === "UPDATE_APPLIED" || row.type === "RECOVERED") || row.type === "UNCHANGED" && !hasMetadata(row, "late") && row.from_bundle_id === null && updateStrategyOf(row) === null;
|
|
35
56
|
/**
|
|
36
57
|
* Throws unless `row` has exactly the bundle event fields, each of its type,
|
|
37
58
|
* and the invariants of its event type: `invalid-field` for an unknown field,
|
|
@@ -44,4 +65,4 @@ const validateBundleEventFields = (row) => {
|
|
|
44
65
|
if (!hasEventInvariants(row)) throw new DatabaseAdapterInputError("invalid-data");
|
|
45
66
|
};
|
|
46
67
|
//#endregion
|
|
47
|
-
export { isDatabaseBundleEventMetadata, isRecord, validateBundleEventFields };
|
|
68
|
+
export { isDatabaseBundleEventMetadata, isRecord, runningBuiltinBundleId, validateBundleEventFields };
|
package/dist/server/index.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_schema = require("./schema.cjs");
|
|
2
3
|
const require_model = require("./model.cjs");
|
|
3
4
|
const require_official = require("./official.cjs");
|
|
4
5
|
const require_errors = require("./errors.cjs");
|
|
5
6
|
const require_provider = require("./provider.cjs");
|
|
6
|
-
const require_schema = require("./schema.cjs");
|
|
7
7
|
const require_recordEvent = require("./recordEvent.cjs");
|
|
8
8
|
const require_reads = require("./reads.cjs");
|
|
9
9
|
const require_routes = require("./routes.cjs");
|
package/dist/server/index.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ import { BundleEventFailure, BundleEventFailureReason, BundleEventFailureStage,
|
|
|
2
2
|
import { InsightsBundleEventFilter, InsightsCountEventSeriesInput, InsightsCountEventsInput, InsightsCountLatestEventsInput, InsightsCoverage, InsightsEventCursor, InsightsEventFilter, InsightsEventSeriesPoint, InsightsFindLatestEventsInput, InsightsGetAppUsageInput, InsightsGetAppUsageResult, InsightsGetReleaseActivityInput, InsightsGetReleaseActivityResult, InsightsListEventsInput, InsightsModel, InsightsRecordEventInput, InsightsScope, InsightsTimeRange, ReleaseActivityMetrics, ReleaseReference } from "./modelTypes.cjs";
|
|
3
3
|
import { DEFAULT_INSIGHTS_RETENTION, InsightsRetention, InsightsSchema, createInsightsSchema, insightsSchema } from "./schema.cjs";
|
|
4
4
|
import { InsightsFailureBreakdown, InsightsUpdateFailures, InsightsUpdateFailuresInput } from "./reads.cjs";
|
|
5
|
-
import { ActiveInstallationWindow, BundleEventFailureInput, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsHttpResponse, InstallationHistoryRow, InstallationRow, ReportingOverview } from "./domain.cjs";
|
|
5
|
+
import { ActiveInstallationWindow, BundleEventFailureInput, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryChange, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsHttpResponse, InstallationHistoryRow, InstallationRow, ReportingOverview } from "./domain.cjs";
|
|
6
6
|
import { InsightsBadRequestError } from "./errors.cjs";
|
|
7
7
|
import { createInsightsModel } from "./model.cjs";
|
|
8
8
|
import { InsightsEventPageInput, InsightsInstallationEventPageInput, InsightsProvider, InsightsUserInstallationPageInput } from "./types.cjs";
|
|
@@ -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";
|
|
@@ -390,4 +422,4 @@ declare const insights: (options?: InsightsOptions) => import("@hot-updater/plug
|
|
|
390
422
|
endpoints: PluginEndpoint[];
|
|
391
423
|
}, {}>;
|
|
392
424
|
//#endregion
|
|
393
|
-
export { type ActiveInstallationWindow, type BundleEventFailure, type BundleEventFailureInput, type BundleEventFailureReason, type BundleEventFailureStage, type BundleEventRow, type BundleEventRowBase, type CreateBundleEventRequest, type CreateBundleEventRequestBase, type CursorPage, DEFAULT_INSIGHTS_RETENTION, type DatabaseBundleEventMetadata, type EventCursorPage, type EventHistoryRow, InsightsApi, InsightsBadRequestError, type InsightsBundleEventFilter, type InsightsBundleSelection, type InsightsCountEventSeriesInput, type InsightsCountEventsInput, type InsightsCountLatestEventsInput, type InsightsCountMeasurement, type InsightsCoverage, type InsightsEventCursor, type InsightsEventFilter, type InsightsEventPageInput, type InsightsEventSeriesPoint, type InsightsFailureBreakdown, type InsightsFindLatestEventsInput, type InsightsGetAppUsageInput, type InsightsGetAppUsageResult, type InsightsGetReleaseActivityInput, type InsightsGetReleaseActivityResult, type InsightsHttpResponse, type InsightsIdentityParts, type InsightsInstallationEventPageInput, type InsightsListEventsInput, type InsightsModel, InsightsOptions, type InsightsProvider, type InsightsRecordEventInput, type InsightsRetention, type InsightsSchema, type InsightsScope, type InsightsTimeRange, type InsightsUpdateFailures, type InsightsUpdateFailuresInput, type InsightsUserInstallationPageInput, type InstallationHistoryRow, type InstallationRow, type ReleaseActivityMetrics, type ReleaseReference, type ReportingOverview, createInsightsModel, createInsightsProvider, createInsightsSchema, insights, insightsIdentity, insightsSchema };
|
|
425
|
+
export { type ActiveInstallationWindow, type BundleEventFailure, type BundleEventFailureInput, type BundleEventFailureReason, type BundleEventFailureStage, type BundleEventRow, type BundleEventRowBase, type CreateBundleEventRequest, type CreateBundleEventRequestBase, type CursorPage, DEFAULT_INSIGHTS_RETENTION, type DatabaseBundleEventMetadata, type EventCursorPage, type EventHistoryChange, type EventHistoryRow, InsightsApi, InsightsBadRequestError, type InsightsBundleEventFilter, type InsightsBundleSelection, type InsightsCountEventSeriesInput, type InsightsCountEventsInput, type InsightsCountLatestEventsInput, type InsightsCountMeasurement, type InsightsCoverage, type InsightsEventCursor, type InsightsEventFilter, type InsightsEventPageInput, type InsightsEventSeriesPoint, type InsightsFailureBreakdown, type InsightsFindLatestEventsInput, type InsightsGetAppUsageInput, type InsightsGetAppUsageResult, type InsightsGetReleaseActivityInput, type InsightsGetReleaseActivityResult, type InsightsHttpResponse, type InsightsIdentityParts, type InsightsInstallationEventPageInput, type InsightsListEventsInput, type InsightsModel, InsightsOptions, type InsightsProvider, type InsightsRecordEventInput, type InsightsRetention, type InsightsSchema, type InsightsScope, type InsightsTimeRange, type InsightsUpdateFailures, type InsightsUpdateFailuresInput, type InsightsUserInstallationPageInput, type InstallationHistoryRow, type InstallationRow, type ReleaseActivityMetrics, type ReleaseReference, type ReportingOverview, createInsightsModel, createInsightsProvider, createInsightsSchema, insights, insightsIdentity, insightsSchema };
|