@hot-updater/firebase 1.0.0-rc.27 → 1.0.0-rc.29
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/firebase/functions/index.cjs +55 -6
- package/dist/index.d.cts +12 -0
- package/dist/index.d.mts +12 -0
- package/package.json +7 -7
|
@@ -4524,7 +4524,7 @@ const createKvAdapter = ({ store, tablePrefix = "" }) => {
|
|
|
4524
4524
|
};
|
|
4525
4525
|
//#endregion
|
|
4526
4526
|
//#region ../../packages/server/dist/version.mjs
|
|
4527
|
-
const HOT_UPDATER_SERVER_VERSION = "1.0.0-rc.
|
|
4527
|
+
const HOT_UPDATER_SERVER_VERSION = "1.0.0-rc.29";
|
|
4528
4528
|
//#endregion
|
|
4529
4529
|
//#region ../../packages/server/dist/handlerVersionRoutes.mjs
|
|
4530
4530
|
/**
|
|
@@ -7684,9 +7684,10 @@ const apiKeys = (options = {}) => {
|
|
|
7684
7684
|
//#region ../insights/dist/server/eventRow.mjs
|
|
7685
7685
|
const isOptional = (value, key, valid) => !Object.hasOwn(value, key) || valid(value[key]);
|
|
7686
7686
|
const isString = (value) => typeof value === "string";
|
|
7687
|
+
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);
|
|
7687
7688
|
/** An `UPDATE_FAILED` report's stored failure: a stage and a reason, and what else the client knew. */
|
|
7688
|
-
const isDatabaseBundleEventFailure = (value) => isDatabaseJsonObject(value) && isString(value.stage) && isString(value.reason) && isOptional(value, "resource", isString) && isOptional(value, "http_status", (status) => Number.isSafeInteger(status)) && isOptional(value, "transport", isString) && isOptional(value, "origin_code", isString) && isOptional(value, "previous_process_exit", isString);
|
|
7689
|
-
const isDatabaseBundleEventMetadata = (value) => isDatabaseJsonObject(value) && typeof value.cohort === "string" && (value.update_strategy === null || value.update_strategy === "fingerprint" || value.update_strategy === "appVersion") && (value.fingerprint_hash === null || typeof value.fingerprint_hash === "string") && (value.sdk_version === null || typeof value.sdk_version === "string") && isOptional(value, "failure", isDatabaseBundleEventFailure) && isOptional(value, "delivery", isString) && isOptional(value, "patch_fallback", (flag) => typeof flag === "boolean") && isOptional(value, "previous_process_exit", isString);
|
|
7689
|
+
const isDatabaseBundleEventFailure = (value) => isDatabaseJsonObject(value) && isString(value.stage) && isString(value.reason) && isOptional(value, "resource", isString) && isOptional(value, "http_status", (status) => Number.isSafeInteger(status)) && isOptional(value, "transport", isString) && isOptional(value, "origin_code", isString) && isOptional(value, "error_message", isString) && isOptional(value, "error_stack", isString) && isOptional(value, "previous_process_exit", isString);
|
|
7690
|
+
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") && isOptional(value, "previous_process_exit", isString);
|
|
7690
7691
|
const isRecord$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7691
7692
|
const isIdentity$1 = (value) => typeof value === "string" && value.length > 0 && value.length <= 255;
|
|
7692
7693
|
const isTextOrNull = (value) => value === null || typeof value === "string";
|
|
@@ -8037,6 +8038,8 @@ function readFailure(value) {
|
|
|
8037
8038
|
const failure = isRecord$1(value) ? value : {};
|
|
8038
8039
|
const httpStatus = failure.httpStatus;
|
|
8039
8040
|
const originCode = readCode(failure.originCode);
|
|
8041
|
+
const errorMessage = typeof failure.errorMessage === "string" && failure.errorMessage.length <= 2048 ? failure.errorMessage : void 0;
|
|
8042
|
+
const errorStack = typeof failure.errorStack === "string" && failure.errorStack.length <= 4096 ? failure.errorStack : void 0;
|
|
8040
8043
|
const previousProcessExit = readCode(failure.previousProcessExit);
|
|
8041
8044
|
return {
|
|
8042
8045
|
stage: oneOf(STAGES, failure.stage),
|
|
@@ -8045,9 +8048,22 @@ function readFailure(value) {
|
|
|
8045
8048
|
...Number.isSafeInteger(httpStatus) && httpStatus >= 100 && httpStatus <= 599 ? { httpStatus } : {},
|
|
8046
8049
|
...failure.transport == null ? {} : { transport: oneOf(TRANSPORTS, failure.transport) },
|
|
8047
8050
|
...originCode === void 0 ? {} : { originCode },
|
|
8051
|
+
...errorMessage === void 0 ? {} : { errorMessage },
|
|
8052
|
+
...errorStack === void 0 ? {} : { errorStack },
|
|
8048
8053
|
...previousProcessExit === void 0 ? {} : { previousProcessExit }
|
|
8049
8054
|
};
|
|
8050
8055
|
}
|
|
8056
|
+
function readHttpResponse(value) {
|
|
8057
|
+
if (!isRecord$1(value) || value.resource !== "catalog" && value.resource !== "artifact" || typeof value.path !== "string" || value.path.length > 1024 || !Number.isSafeInteger(value.status) || value.status < 100 || value.status > 599 || value.body !== null && (typeof value.body !== "string" || new TextEncoder().encode(JSON.stringify(value.body)).byteLength > 4096) || typeof value.bodyTruncated !== "boolean" || !Number.isSafeInteger(value.receivedAtMs) || value.receivedAtMs < 0) throw new InsightsBadRequestError("Invalid HTTP response details");
|
|
8058
|
+
return {
|
|
8059
|
+
resource: value.resource,
|
|
8060
|
+
path: value.path,
|
|
8061
|
+
status: value.status,
|
|
8062
|
+
body: value.body,
|
|
8063
|
+
bodyTruncated: value.bodyTruncated,
|
|
8064
|
+
receivedAtMs: value.receivedAtMs
|
|
8065
|
+
};
|
|
8066
|
+
}
|
|
8051
8067
|
async function readBoundedText(request) {
|
|
8052
8068
|
const contentLength = request.headers.get("content-length");
|
|
8053
8069
|
const declaredByteLength = Number(contentLength);
|
|
@@ -8083,7 +8099,10 @@ function requireEvent(payload) {
|
|
|
8083
8099
|
const platform = requireStringField(payload, "platform");
|
|
8084
8100
|
if (platform !== "ios" && platform !== "android") throw new InsightsBadRequestError("Invalid event field: platform");
|
|
8085
8101
|
const eventId = readEventId(payload);
|
|
8102
|
+
const metadata = readMetadata(payload);
|
|
8103
|
+
const httpMetadata = metadata.httpResponse === void 0 ? {} : { httpResponse: readHttpResponse(metadata.httpResponse) };
|
|
8086
8104
|
const base = {
|
|
8105
|
+
...metadata.httpResponse === void 0 ? {} : { metadata: httpMetadata },
|
|
8087
8106
|
...eventId === void 0 ? {} : { eventId },
|
|
8088
8107
|
installId: requireIdentityField(payload, "installId"),
|
|
8089
8108
|
toBundleId: requireStringField(payload, "toBundleId"),
|
|
@@ -8107,11 +8126,11 @@ function requireEvent(payload) {
|
|
|
8107
8126
|
updateStrategy
|
|
8108
8127
|
};
|
|
8109
8128
|
};
|
|
8110
|
-
const metadata = readMetadata(payload);
|
|
8111
8129
|
switch (type) {
|
|
8112
8130
|
case "UPDATE_DOWNLOADED": {
|
|
8113
8131
|
const delivery = metadata.delivery;
|
|
8114
8132
|
const read = {
|
|
8133
|
+
...httpMetadata,
|
|
8115
8134
|
...delivery == null ? {} : { delivery: oneOf(DELIVERIES, delivery) },
|
|
8116
8135
|
...metadata.patchFallback === true ? { patchFallback: true } : {}
|
|
8117
8136
|
};
|
|
@@ -8130,13 +8149,19 @@ function requireEvent(payload) {
|
|
|
8130
8149
|
return {
|
|
8131
8150
|
...movement(),
|
|
8132
8151
|
type,
|
|
8133
|
-
...previousProcessExit === void 0 ? {} : { metadata: {
|
|
8152
|
+
...previousProcessExit === void 0 ? {} : { metadata: {
|
|
8153
|
+
...httpMetadata,
|
|
8154
|
+
previousProcessExit
|
|
8155
|
+
} }
|
|
8134
8156
|
};
|
|
8135
8157
|
}
|
|
8136
8158
|
case "UPDATE_FAILED": return {
|
|
8137
8159
|
...movement(),
|
|
8138
8160
|
type,
|
|
8139
|
-
metadata: {
|
|
8161
|
+
metadata: {
|
|
8162
|
+
...httpMetadata,
|
|
8163
|
+
failure: readFailure(metadata.failure)
|
|
8164
|
+
}
|
|
8140
8165
|
};
|
|
8141
8166
|
case "UNCHANGED":
|
|
8142
8167
|
if (payload.fromBundleId !== null || payload.updateStrategy !== null) throw new InsightsBadRequestError("Invalid unchanged event shape");
|
|
@@ -8166,7 +8191,16 @@ function createBundleEventRow(input) {
|
|
|
8166
8191
|
to_release_id: input.toReleaseId,
|
|
8167
8192
|
user_id: input.userId ?? null
|
|
8168
8193
|
};
|
|
8194
|
+
const response = input.metadata?.httpResponse;
|
|
8169
8195
|
const metadata = {
|
|
8196
|
+
...response ? { http_response: {
|
|
8197
|
+
resource: response.resource,
|
|
8198
|
+
path: response.path,
|
|
8199
|
+
status: response.status,
|
|
8200
|
+
body: response.body,
|
|
8201
|
+
body_truncated: response.bodyTruncated,
|
|
8202
|
+
received_at_ms: response.receivedAtMs
|
|
8203
|
+
} } : {},
|
|
8170
8204
|
cohort: input.cohort,
|
|
8171
8205
|
fingerprint_hash: input.fingerprintHash,
|
|
8172
8206
|
sdk_version: input.sdkVersion ?? null,
|
|
@@ -8215,6 +8249,8 @@ function createBundleEventRow(input) {
|
|
|
8215
8249
|
failure: {
|
|
8216
8250
|
stage: failure.stage,
|
|
8217
8251
|
reason: failure.reason,
|
|
8252
|
+
...failure.errorMessage === void 0 ? {} : { error_message: failure.errorMessage },
|
|
8253
|
+
...failure.errorStack === void 0 ? {} : { error_stack: failure.errorStack },
|
|
8218
8254
|
...failure.resource === void 0 ? {} : { resource: failure.resource },
|
|
8219
8255
|
...failure.httpStatus === void 0 ? {} : { http_status: failure.httpStatus },
|
|
8220
8256
|
...failure.transport === void 0 ? {} : { transport: failure.transport },
|
|
@@ -8378,6 +8414,8 @@ const assertEventRows = (rows, input) => {
|
|
|
8378
8414
|
const toFailure = (failure) => ({
|
|
8379
8415
|
stage: failure.stage,
|
|
8380
8416
|
reason: failure.reason,
|
|
8417
|
+
...failure.error_message === void 0 ? {} : { errorMessage: failure.error_message },
|
|
8418
|
+
...failure.error_stack === void 0 ? {} : { errorStack: failure.error_stack },
|
|
8381
8419
|
...failure.resource === void 0 ? {} : { resource: failure.resource },
|
|
8382
8420
|
...failure.http_status === void 0 ? {} : { httpStatus: failure.http_status },
|
|
8383
8421
|
...failure.transport === void 0 ? {} : { transport: failure.transport },
|
|
@@ -8386,12 +8424,22 @@ const toFailure = (failure) => ({
|
|
|
8386
8424
|
});
|
|
8387
8425
|
/** What a row's metadata adds for its type: a failure, a delivery, an exit reason. */
|
|
8388
8426
|
const eventDetails = ({ type, metadata }) => ({
|
|
8427
|
+
...metadata.http_response !== void 0 ? { httpResponse: {
|
|
8428
|
+
resource: metadata.http_response.resource,
|
|
8429
|
+
path: metadata.http_response.path,
|
|
8430
|
+
status: metadata.http_response.status,
|
|
8431
|
+
body: metadata.http_response.body,
|
|
8432
|
+
bodyTruncated: metadata.http_response.body_truncated,
|
|
8433
|
+
receivedAtMs: metadata.http_response.received_at_ms
|
|
8434
|
+
} } : {},
|
|
8389
8435
|
...type === "UPDATE_FAILED" && metadata.failure !== void 0 ? { failure: toFailure(metadata.failure) } : {},
|
|
8390
8436
|
...type === "UPDATE_DOWNLOADED" && metadata.delivery !== void 0 ? { delivery: metadata.delivery } : {},
|
|
8391
8437
|
...type === "UPDATE_DOWNLOADED" && metadata.patch_fallback === true ? { patchFallback: true } : {},
|
|
8392
8438
|
...type === "RECOVERED" && metadata.previous_process_exit !== void 0 ? { previousProcessExit: metadata.previous_process_exit } : {}
|
|
8393
8439
|
});
|
|
8394
8440
|
const toEventHistoryRow = (row) => ({
|
|
8441
|
+
...row.to_release_id == null ? {} : { toReleaseId: row.to_release_id },
|
|
8442
|
+
...row.metadata.sdk_version == null ? {} : { sdkVersion: row.metadata.sdk_version },
|
|
8395
8443
|
appVersion: row.app_version,
|
|
8396
8444
|
channel: row.channel,
|
|
8397
8445
|
cohort: row.metadata.cohort,
|
|
@@ -8406,6 +8454,7 @@ const toEventHistoryRow = (row) => ({
|
|
|
8406
8454
|
...eventDetails(row)
|
|
8407
8455
|
});
|
|
8408
8456
|
const toInstallationRow = (row) => ({
|
|
8457
|
+
...eventDetails(row).httpResponse ? { httpResponse: eventDetails(row).httpResponse } : {},
|
|
8409
8458
|
appVersion: row.app_version,
|
|
8410
8459
|
channel: row.channel,
|
|
8411
8460
|
cohort: row.metadata.cohort,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DatabaseJsonObject, EngineDatabase, Platform, PluginTables, StorageAdapterWith } from "@hot-updater/plugin-core";
|
|
2
2
|
import { AppOptions } from "firebase-admin/app";
|
|
3
|
+
import "@hot-updater/protocol";
|
|
3
4
|
//#region src/firebaseDatabase.d.ts
|
|
4
5
|
type FirebaseDatabaseConfig = AppOptions & {
|
|
5
6
|
/** The one collection the database keeps its items in. */
|
|
@@ -50,9 +51,19 @@ type BundleEventFailure = DatabaseJsonObject & {
|
|
|
50
51
|
readonly transport?: "timeout" | "dns" | "tls" | "connection" | "offline" | "cancelled" | "unknown";
|
|
51
52
|
/** The storage origin's error code, such as `ExpiredToken`. */
|
|
52
53
|
readonly origin_code?: string;
|
|
54
|
+
readonly error_message?: string;
|
|
55
|
+
readonly error_stack?: string;
|
|
53
56
|
/** Android's `ApplicationExitInfo` reason for the process before this one. */
|
|
54
57
|
readonly previous_process_exit?: string;
|
|
55
58
|
};
|
|
59
|
+
type DatabaseHttpResponse = DatabaseJsonObject & {
|
|
60
|
+
readonly resource: "catalog" | "artifact";
|
|
61
|
+
readonly path: string;
|
|
62
|
+
readonly status: number;
|
|
63
|
+
readonly body: string | null;
|
|
64
|
+
readonly body_truncated: boolean;
|
|
65
|
+
readonly received_at_ms: number;
|
|
66
|
+
};
|
|
56
67
|
/** Ancillary report data; queryable identity and lifecycle fields stay on the row. */
|
|
57
68
|
type DatabaseBundleEventMetadata = DatabaseJsonObject & {
|
|
58
69
|
readonly cohort: string;
|
|
@@ -61,6 +72,7 @@ type DatabaseBundleEventMetadata = DatabaseJsonObject & {
|
|
|
61
72
|
readonly sdk_version: string | null;
|
|
62
73
|
/** `UPDATE_FAILED`: what failed. */
|
|
63
74
|
readonly failure?: BundleEventFailure;
|
|
75
|
+
readonly http_response?: DatabaseHttpResponse;
|
|
64
76
|
/** `UPDATE_DOWNLOADED`: how the bundle arrived. */
|
|
65
77
|
readonly delivery?: "patch" | "manifest" | "archive" | "unknown";
|
|
66
78
|
/** `UPDATE_DOWNLOADED`: a patch failed and the full files came instead. */
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DatabaseJsonObject, EngineDatabase, Platform, PluginTables, StorageAdapterWith } from "@hot-updater/plugin-core";
|
|
2
2
|
import { AppOptions } from "firebase-admin/app";
|
|
3
|
+
import "@hot-updater/protocol";
|
|
3
4
|
//#region src/firebaseDatabase.d.ts
|
|
4
5
|
type FirebaseDatabaseConfig = AppOptions & {
|
|
5
6
|
/** The one collection the database keeps its items in. */
|
|
@@ -50,9 +51,19 @@ type BundleEventFailure = DatabaseJsonObject & {
|
|
|
50
51
|
readonly transport?: "timeout" | "dns" | "tls" | "connection" | "offline" | "cancelled" | "unknown";
|
|
51
52
|
/** The storage origin's error code, such as `ExpiredToken`. */
|
|
52
53
|
readonly origin_code?: string;
|
|
54
|
+
readonly error_message?: string;
|
|
55
|
+
readonly error_stack?: string;
|
|
53
56
|
/** Android's `ApplicationExitInfo` reason for the process before this one. */
|
|
54
57
|
readonly previous_process_exit?: string;
|
|
55
58
|
};
|
|
59
|
+
type DatabaseHttpResponse = DatabaseJsonObject & {
|
|
60
|
+
readonly resource: "catalog" | "artifact";
|
|
61
|
+
readonly path: string;
|
|
62
|
+
readonly status: number;
|
|
63
|
+
readonly body: string | null;
|
|
64
|
+
readonly body_truncated: boolean;
|
|
65
|
+
readonly received_at_ms: number;
|
|
66
|
+
};
|
|
56
67
|
/** Ancillary report data; queryable identity and lifecycle fields stay on the row. */
|
|
57
68
|
type DatabaseBundleEventMetadata = DatabaseJsonObject & {
|
|
58
69
|
readonly cohort: string;
|
|
@@ -61,6 +72,7 @@ type DatabaseBundleEventMetadata = DatabaseJsonObject & {
|
|
|
61
72
|
readonly sdk_version: string | null;
|
|
62
73
|
/** `UPDATE_FAILED`: what failed. */
|
|
63
74
|
readonly failure?: BundleEventFailure;
|
|
75
|
+
readonly http_response?: DatabaseHttpResponse;
|
|
64
76
|
/** `UPDATE_DOWNLOADED`: how the bundle arrived. */
|
|
65
77
|
readonly delivery?: "patch" | "manifest" | "archive" | "unknown";
|
|
66
78
|
/** `UPDATE_DOWNLOADED`: a patch failed and the full files came instead. */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/firebase",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.29",
|
|
5
5
|
"description": "React Native OTA solution for self-hosted",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"types": "dist/index.d.cts",
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"hono": "4.12.34",
|
|
40
|
-
"@hot-updater/cli-tools": "1.0.0-rc.
|
|
41
|
-
"@hot-updater/
|
|
42
|
-
"@hot-updater/
|
|
43
|
-
"@hot-updater/
|
|
40
|
+
"@hot-updater/cli-tools": "1.0.0-rc.29",
|
|
41
|
+
"@hot-updater/protocol": "1.0.0-rc.28",
|
|
42
|
+
"@hot-updater/plugin-core": "1.0.0-rc.28",
|
|
43
|
+
"@hot-updater/server": "1.0.0-rc.29"
|
|
44
44
|
},
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
"firebase-tools": "15.29.0",
|
|
56
56
|
"fkill": "^9.0.0",
|
|
57
57
|
"mime": "^4.0.4",
|
|
58
|
-
"@hot-updater/mock": "1.0.0-rc.
|
|
59
|
-
"@hot-updater/test-utils": "1.0.0-rc.
|
|
58
|
+
"@hot-updater/mock": "1.0.0-rc.28",
|
|
59
|
+
"@hot-updater/test-utils": "1.0.0-rc.28"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"firebase-admin": "*",
|