@hot-updater/server 0.36.6 → 1.0.0-rc.0
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/adapters/databaseConstraintErrors.cjs +23 -0
- package/dist/adapters/databaseConstraintErrors.mjs +21 -0
- package/dist/adapters/databasePluginUtils.cjs +117 -0
- package/dist/adapters/databasePluginUtils.mjs +106 -0
- package/dist/adapters/drizzle.cjs +53 -176
- package/dist/adapters/drizzle.d.cts +6 -4
- package/dist/adapters/drizzle.d.mts +6 -4
- package/dist/adapters/drizzle.mjs +54 -177
- package/dist/adapters/drizzleCrud.cjs +250 -0
- package/dist/adapters/drizzleCrud.mjs +249 -0
- package/dist/adapters/drizzleLazyDB.cjs +84 -36
- package/dist/adapters/drizzleLazyDB.mjs +84 -36
- package/dist/adapters/drizzleQuery.cjs +68 -0
- package/dist/adapters/drizzleQuery.mjs +67 -0
- package/dist/adapters/kysely.cjs +18 -138
- package/dist/adapters/kysely.d.cts +3 -12
- package/dist/adapters/kysely.d.mts +3 -12
- package/dist/adapters/kysely.mjs +19 -139
- package/dist/adapters/kyselyCrud.cjs +254 -0
- package/dist/adapters/kyselyCrud.mjs +253 -0
- package/dist/adapters/kyselyQuery.cjs +56 -0
- package/dist/adapters/kyselyQuery.mjs +55 -0
- package/dist/adapters/mongodb.cjs +21 -174
- package/dist/adapters/mongodb.d.cts +3 -2
- package/dist/adapters/mongodb.d.mts +3 -2
- package/dist/adapters/mongodb.mjs +21 -174
- package/dist/adapters/mongodbCollections.cjs +36 -0
- package/dist/adapters/mongodbCollections.mjs +30 -0
- package/dist/adapters/mongodbQuery.cjs +77 -0
- package/dist/adapters/mongodbQuery.mjs +70 -0
- package/dist/adapters/mongodbReads.cjs +148 -0
- package/dist/adapters/mongodbReads.mjs +147 -0
- package/dist/adapters/mongodbWrites.cjs +134 -0
- package/dist/adapters/mongodbWrites.mjs +133 -0
- package/dist/adapters/prisma.cjs +205 -180
- package/dist/adapters/prisma.d.cts +3 -3
- package/dist/adapters/prisma.d.mts +3 -3
- package/dist/adapters/prisma.mjs +206 -181
- package/dist/adapters/prismaQuery.cjs +58 -0
- package/dist/adapters/prismaQuery.mjs +56 -0
- package/dist/adapters/prismaRows.cjs +198 -0
- package/dist/adapters/prismaRows.mjs +188 -0
- package/dist/analytics/bounded/activeOverview.cjs +87 -0
- package/dist/analytics/bounded/activeOverview.mjs +85 -0
- package/dist/analytics/bounded/installationSearch.cjs +42 -0
- package/dist/analytics/bounded/installationSearch.mjs +42 -0
- package/dist/analytics/bounded/persistence.cjs +39 -0
- package/dist/analytics/bounded/persistence.mjs +38 -0
- package/dist/analytics/bounded/provider.cjs +170 -0
- package/dist/analytics/bounded/provider.d.cts +7 -0
- package/dist/analytics/bounded/provider.d.mts +7 -0
- package/dist/analytics/bounded/provider.mjs +170 -0
- package/dist/analytics/bounded/scan.cjs +144 -0
- package/dist/analytics/bounded/scan.mjs +138 -0
- package/dist/analytics/domain.d.cts +121 -0
- package/dist/analytics/domain.d.mts +121 -0
- package/dist/analytics/errors.cjs +22 -0
- package/dist/analytics/errors.mjs +20 -0
- package/dist/analytics/eventInput.cjs +111 -0
- package/dist/analytics/eventInput.mjs +111 -0
- package/dist/analytics/persistence.d.cts +6 -0
- package/dist/analytics/persistence.d.mts +6 -0
- package/dist/analytics/queryInput.cjs +58 -0
- package/dist/analytics/queryInput.mjs +55 -0
- package/dist/analytics/routes.cjs +63 -0
- package/dist/analytics/routes.mjs +61 -0
- package/dist/analytics/types.d.cts +17 -0
- package/dist/analytics/types.d.mts +17 -0
- package/dist/apiKeys.cjs +139 -0
- package/dist/apiKeys.d.cts +50 -0
- package/dist/apiKeys.d.mts +50 -0
- package/dist/apiKeys.mjs +133 -0
- package/dist/createHotUpdaterCore.cjs +48 -26
- package/dist/createHotUpdaterCore.d.cts +49 -17
- package/dist/createHotUpdaterCore.d.mts +49 -17
- package/dist/createHotUpdaterCore.mjs +51 -29
- package/dist/db/createBundleDiff.cjs +45 -68
- package/dist/db/createBundleDiff.d.cts +3 -3
- package/dist/db/createBundleDiff.d.mts +3 -3
- package/dist/db/createBundleDiff.mjs +47 -68
- package/dist/db/databasePluginCore.cjs +138 -0
- package/dist/db/databasePluginCore.mjs +137 -0
- package/dist/db/fixedMigrator.cjs +36 -93
- package/dist/db/fixedMigrator.mjs +36 -93
- package/dist/db/fixedMigratorMongo.cjs +319 -0
- package/dist/db/fixedMigratorMongo.mjs +319 -0
- package/dist/db/fixedMigratorShared.cjs +23 -0
- package/dist/db/fixedMigratorShared.mjs +18 -0
- package/dist/db/mongoMigrationExecution.cjs +11 -0
- package/dist/db/mongoMigrationExecution.mjs +11 -0
- package/dist/db/releaseCatalog.cjs +66 -0
- package/dist/db/releaseCatalog.d.cts +17 -0
- package/dist/db/releaseCatalog.d.mts +17 -0
- package/dist/db/releaseCatalog.mjs +64 -0
- package/dist/db/schema/mongodb.cjs +14 -6
- package/dist/db/schema/mongodb.mjs +14 -6
- package/dist/db/schema/registry.cjs +0 -2
- package/dist/db/schema/registry.mjs +1 -2
- package/dist/db/schema/sql.cjs +31 -14
- package/dist/db/schema/sql.mjs +32 -13
- package/dist/db/schema/sqlOperations.cjs +4 -4
- package/dist/db/schema/sqlOperations.mjs +5 -5
- package/dist/db/schemaGenerators.cjs +52 -18
- package/dist/db/schemaGenerators.mjs +52 -18
- package/dist/db/schemaReadiness.cjs +4 -3
- package/dist/db/schemaReadiness.mjs +4 -3
- package/dist/db/sqlMigrationExecution.cjs +67 -0
- package/dist/db/sqlMigrationExecution.mjs +66 -0
- package/dist/db/types.cjs +2 -6
- package/dist/db/types.d.cts +60 -16
- package/dist/db/types.d.mts +60 -16
- package/dist/db/types.mjs +3 -6
- package/dist/db/updateArtifacts.cjs +114 -60
- package/dist/db/updateArtifacts.mjs +117 -62
- package/dist/handler.cjs +108 -282
- package/dist/handler.d.cts +3 -46
- package/dist/handler.d.mts +3 -46
- package/dist/handler.mjs +107 -281
- package/dist/handlerBundleRoutes.cjs +155 -0
- package/dist/handlerBundleRoutes.mjs +155 -0
- package/dist/handlerErrors.cjs +9 -0
- package/dist/handlerErrors.mjs +9 -0
- package/dist/handlerParameters.cjs +39 -0
- package/dist/handlerParameters.mjs +34 -0
- package/dist/handlerReleaseCatalogRoutes.cjs +111 -0
- package/dist/handlerReleaseCatalogRoutes.mjs +110 -0
- package/dist/handlerReleaseManagementRoutes.cjs +125 -0
- package/dist/handlerReleaseManagementRoutes.mjs +124 -0
- package/dist/handlerTypes.d.cts +63 -0
- package/dist/handlerTypes.d.mts +63 -0
- package/dist/handlerVersionRoutes.cjs +10 -0
- package/dist/handlerVersionRoutes.d.cts +4 -0
- package/dist/handlerVersionRoutes.d.mts +4 -0
- package/dist/handlerVersionRoutes.mjs +9 -0
- package/dist/index.cjs +10 -1
- package/dist/index.d.cts +9 -3
- package/dist/index.d.mts +9 -3
- package/dist/index.mjs +5 -2
- package/dist/node.cjs +19 -12
- package/dist/node.d.cts +15 -10
- package/dist/node.d.mts +15 -10
- package/dist/node.mjs +19 -13
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/schema/dsl.cjs +19 -2
- package/dist/schema/dsl.mjs +17 -3
- package/dist/schema/index.cjs +1 -8
- package/dist/schema/index.mjs +2 -8
- package/dist/schema/types.cjs +3 -1
- package/dist/schema/types.mjs +3 -2
- package/dist/schema/v1_0_0.cjs +364 -0
- package/dist/schema/v1_0_0.mjs +357 -0
- package/dist/storageAccess.cjs +69 -25
- package/dist/storageAccess.mjs +68 -25
- package/dist/types/index.d.cts +4 -3
- package/dist/types/index.d.mts +5 -4
- package/package.json +8 -7
- package/src/adapters/databaseConstraintErrors.ts +25 -0
- package/src/adapters/databasePluginTestDatabase.ts +106 -0
- package/src/adapters/databasePluginUtils.spec.ts +29 -0
- package/src/adapters/databasePluginUtils.ts +214 -0
- package/src/adapters/drizzle.spec.ts +208 -47
- package/src/adapters/drizzle.ts +106 -293
- package/src/adapters/drizzleCrud.ts +419 -0
- package/src/adapters/drizzleLazyDB.ts +206 -100
- package/src/adapters/drizzleQuery.ts +164 -0
- package/src/adapters/kysely.spec.ts +126 -88
- package/src/adapters/kysely.ts +76 -334
- package/src/adapters/kyselyCrud.ts +588 -0
- package/src/adapters/kyselyQuery.ts +128 -0
- package/src/adapters/mongodb.spec.ts +141 -0
- package/src/adapters/mongodb.ts +60 -288
- package/src/adapters/mongodbCollections.ts +62 -0
- package/src/adapters/mongodbQuery.ts +226 -0
- package/src/adapters/mongodbReads.ts +311 -0
- package/src/adapters/mongodbRows.spec.ts +64 -0
- package/src/adapters/mongodbRows.ts +118 -0
- package/src/adapters/mongodbTestClient.ts +342 -0
- package/src/adapters/mongodbTestFilter.ts +166 -0
- package/src/adapters/mongodbWrites.ts +260 -0
- package/src/adapters/prisma.spec.ts +196 -0
- package/src/adapters/prisma.ts +417 -292
- package/src/adapters/prismaQuery.ts +129 -0
- package/src/adapters/prismaRows.spec.ts +98 -0
- package/src/adapters/prismaRows.ts +301 -0
- package/src/adapters/prismaTestClient.ts +396 -0
- package/src/analytics/analytics.integration.spec.ts +144 -0
- package/src/analytics/bounded/activeOverview.spec.ts +189 -0
- package/src/analytics/bounded/activeOverview.ts +148 -0
- package/src/analytics/bounded/installationSearch.spec.ts +130 -0
- package/src/analytics/bounded/installationSearch.ts +69 -0
- package/src/analytics/bounded/persistence.ts +43 -0
- package/src/analytics/bounded/provider.spec.ts +219 -0
- package/src/analytics/bounded/provider.ts +229 -0
- package/src/analytics/bounded/scan.ts +235 -0
- package/src/analytics/domain.ts +139 -0
- package/src/analytics/errors.ts +18 -0
- package/src/analytics/eventInput.ts +168 -0
- package/src/analytics/persistence.ts +10 -0
- package/src/analytics/queryInput.ts +102 -0
- package/src/analytics/routes.ts +123 -0
- package/src/analytics/types.ts +44 -0
- package/src/apiKeys.integration.spec.ts +192 -0
- package/src/apiKeys.spec.ts +162 -0
- package/src/apiKeys.ts +220 -0
- package/src/createHotUpdaterCore.ts +164 -100
- package/src/db/bundleRows.spec.ts +164 -0
- package/src/db/bundleRows.ts +10 -140
- package/src/db/createBundleDiff.spec.ts +172 -127
- package/src/db/createBundleDiff.ts +91 -110
- package/src/db/databasePluginCore.spec.ts +62 -0
- package/src/db/databasePluginCore.testFixtures.ts +76 -0
- package/src/db/databasePluginCore.ts +185 -0
- package/src/db/databasePluginUpdateCheck.bench.ts +107 -0
- package/src/db/fixedMigrator.spec.ts +184 -42
- package/src/db/fixedMigrator.ts +64 -205
- package/src/db/fixedMigratorMongo.spec.ts +192 -0
- package/src/db/fixedMigratorMongo.ts +425 -0
- package/src/db/fixedMigratorShared.ts +36 -0
- package/src/db/hotUpdaterSchema.ts +0 -1
- package/src/db/index.spec.ts +333 -1025
- package/src/db/mongoMigrationExecution.ts +23 -0
- package/src/db/node-sqlite.d.ts +25 -0
- package/src/db/releaseCatalog.ts +148 -0
- package/src/db/schema/mongodb.ts +20 -6
- package/src/db/schema/sql.ts +52 -11
- package/src/db/schema/sqlOperations.ts +5 -4
- package/src/db/schemaGenerators.ts +107 -23
- package/src/db/schemaReadiness.ts +2 -1
- package/src/db/sqlMigrationExecution.spec.ts +65 -0
- package/src/db/sqlMigrationExecution.ts +108 -0
- package/src/db/types.spec.ts +55 -0
- package/src/db/types.ts +129 -65
- package/src/db/updateArtifacts.spec.ts +359 -0
- package/src/db/updateArtifacts.ts +290 -126
- package/src/handler-standalone.integration.spec.ts +401 -364
- package/src/handler.spec.ts +137 -582
- package/src/handler.testFixtures.ts +30 -0
- package/src/handler.ts +218 -616
- package/src/handlerAuth.integration.spec.ts +33 -0
- package/src/handlerBundleRoutes.ts +259 -0
- package/src/handlerErrors.ts +7 -0
- package/src/handlerManagement.spec.ts +262 -0
- package/src/handlerParameters.ts +105 -0
- package/src/handlerReleaseCatalogRoutes.ts +154 -0
- package/src/handlerReleaseManagementRoutes.ts +213 -0
- package/src/handlerTypes.ts +96 -0
- package/src/handlerVersionRoutes.ts +12 -0
- package/src/index.ts +22 -2
- package/src/node.spec.ts +79 -10
- package/src/node.ts +20 -17
- package/src/releaseCatalogRoutes.integration.spec.ts +238 -0
- package/src/runtime.spec.ts +126 -959
- package/src/runtime.testFixtures.ts +71 -0
- package/src/schema/dsl-all-versions.spec.ts +26 -17
- package/src/schema/dsl.ts +41 -2
- package/src/schema/index.ts +3 -9
- package/src/schema/types.ts +9 -3
- package/src/schema/v1_0_0.spec.ts +146 -0
- package/src/schema/v1_0_0.ts +465 -0
- package/src/storageAccess.spec.ts +127 -32
- package/src/storageAccess.ts +106 -55
- package/src/types/index.ts +2 -1
- package/dist/db/bundleRows.cjs +0 -82
- package/dist/db/bundleRows.d.cts +0 -33
- package/dist/db/bundleRows.d.mts +0 -33
- package/dist/db/bundleRows.mjs +0 -79
- package/dist/db/pluginCore.cjs +0 -242
- package/dist/db/pluginCore.mjs +0 -241
- package/dist/db/schema/sqlMigrations.cjs +0 -74
- package/dist/db/schema/sqlMigrations.mjs +0 -73
- package/dist/db/schemaEnhancements.cjs +0 -20
- package/dist/db/schemaEnhancements.mjs +0 -19
- package/dist/route.cjs +0 -7
- package/dist/route.mjs +0 -7
- package/dist/schema/v0_21_0.cjs +0 -38
- package/dist/schema/v0_21_0.mjs +0 -37
- package/dist/schema/v0_29_0.cjs +0 -45
- package/dist/schema/v0_29_0.mjs +0 -44
- package/dist/schema/v0_31_0.cjs +0 -82
- package/dist/schema/v0_31_0.mjs +0 -80
- package/src/db/pluginCore.spec.ts +0 -1095
- package/src/db/pluginCore.ts +0 -475
- package/src/db/pluginUpdateCheck.bench.ts +0 -254
- package/src/db/schema/sqlMigrations.ts +0 -219
- package/src/db/schemaEnhancements.ts +0 -55
- package/src/route.ts +0 -7
- package/src/schema/v0_21_0.ts +0 -52
- package/src/schema/v0_29_0.ts +0 -62
- package/src/schema/v0_31_0.spec.ts +0 -73
- package/src/schema/v0_31_0.ts +0 -120
|
@@ -1,50 +1,72 @@
|
|
|
1
1
|
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
2
|
const require_handler = require("./handler.cjs");
|
|
3
|
-
const
|
|
3
|
+
const require_provider = require("./analytics/bounded/provider.cjs");
|
|
4
|
+
const require_apiKeys = require("./apiKeys.cjs");
|
|
5
|
+
const require_databasePluginCore = require("./db/databasePluginCore.cjs");
|
|
4
6
|
const require_schemaReadiness = require("./db/schemaReadiness.cjs");
|
|
5
7
|
const require_types = require("./db/types.cjs");
|
|
6
|
-
const require_route = require("./route.cjs");
|
|
7
8
|
const require_storageAccess = require("./storageAccess.cjs");
|
|
8
9
|
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
9
10
|
//#region src/createHotUpdaterCore.ts
|
|
11
|
+
const normalizeClientAccess = (value) => {
|
|
12
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new TypeError("clientAccess must be an object.");
|
|
13
|
+
const policy = value;
|
|
14
|
+
if (policy.type === "public") return { type: "public" };
|
|
15
|
+
if (policy.type === "api-key") return {
|
|
16
|
+
headerName: require_apiKeys.normalizeApiKeyHeaderName(policy.headerName),
|
|
17
|
+
type: "api-key"
|
|
18
|
+
};
|
|
19
|
+
throw new TypeError("clientAccess.type must be either \"public\" or \"api-key\".");
|
|
20
|
+
};
|
|
10
21
|
const hotUpdaterCoreMetadata = Symbol.for("@hot-updater/server/core-metadata");
|
|
11
22
|
function getHotUpdaterCoreMetadata(hotUpdater) {
|
|
12
23
|
return hotUpdater[hotUpdaterCoreMetadata];
|
|
13
24
|
}
|
|
14
25
|
function createHotUpdaterCore(options) {
|
|
26
|
+
for (const key of ["authorityId", "catalogId"]) if (Object.hasOwn(options, key)) throw new TypeError(`Remove ${key} from createHotUpdater options. Catalog identity is managed internally.`);
|
|
15
27
|
const database = options.database;
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
(0, _hot_updater_plugin_core.assertRuntimeStoragePlugin)(storagePlugin);
|
|
20
|
-
return storagePlugin;
|
|
28
|
+
const { downloadStorageObject, readStorageText, resolveFileUrl } = require_storageAccess.createStorageAccess((options.storage ?? []).map((storage) => {
|
|
29
|
+
(0, _hot_updater_plugin_core.assertStorageOperations)(storage, ["get", "getDownloadUrl"]);
|
|
30
|
+
return storage;
|
|
21
31
|
}));
|
|
22
|
-
if (!require_types.isDatabasePluginFactory(database) && !require_types.isDatabasePlugin(database)) throw new Error("@hot-updater/server only supports database plugins.");
|
|
23
32
|
const adapterCapabilities = database;
|
|
24
|
-
|
|
33
|
+
if (!require_types.isDatabasePlugin(database)) throw new Error("@hot-updater/server only supports database plugins.");
|
|
34
|
+
const plugin = database;
|
|
25
35
|
const assertSchemaReady = require_schemaReadiness.createSchemaReadinessChecker(adapterCapabilities.adapterName ?? plugin.name, adapterCapabilities.createMigrator);
|
|
26
|
-
const core =
|
|
27
|
-
createMutationPlugin: () => database(),
|
|
28
|
-
beforeOperation: assertSchemaReady,
|
|
29
|
-
readStorageText
|
|
30
|
-
} : {
|
|
36
|
+
const core = require_databasePluginCore.createDatabasePluginCore(plugin, resolveFileUrl, {
|
|
31
37
|
beforeOperation: assertSchemaReady,
|
|
32
38
|
readStorageText
|
|
33
39
|
});
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
const clientAccess = normalizeClientAccess(options.clientAccess);
|
|
41
|
+
const analytics = require_provider.createAnalyticsProvider({
|
|
42
|
+
async append(row) {
|
|
43
|
+
await assertSchemaReady();
|
|
44
|
+
return plugin.models.analytics.append(row);
|
|
45
|
+
},
|
|
46
|
+
async scan(input) {
|
|
47
|
+
await assertSchemaReady();
|
|
48
|
+
return plugin.models.analytics.scan(input);
|
|
49
|
+
}
|
|
37
50
|
});
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
};
|
|
42
|
-
const
|
|
43
|
-
|
|
51
|
+
const apiKeys = require_apiKeys.createApiKeyManagement({
|
|
52
|
+
apiKeys: plugin.models.apiKeys,
|
|
53
|
+
beforeOperation: assertSchemaReady
|
|
54
|
+
});
|
|
55
|
+
const handlers = require_handler.createHotUpdaterHandlers(core.api, analytics, clientAccess.type === "api-key" ? {
|
|
56
|
+
authenticate: (request) => require_apiKeys.authenticateApiKey({
|
|
57
|
+
apiKeys: plugin.models.apiKeys,
|
|
58
|
+
beforeLookup: assertSchemaReady,
|
|
59
|
+
headerName: clientAccess.headerName,
|
|
60
|
+
request
|
|
61
|
+
}),
|
|
62
|
+
headerName: clientAccess.headerName
|
|
63
|
+
} : void 0, downloadStorageObject);
|
|
64
|
+
const api = Object.assign({
|
|
44
65
|
adapterName: adapterCapabilities.adapterName ?? core.adapterName,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
66
|
+
analytics,
|
|
67
|
+
apiKeys,
|
|
68
|
+
handlers
|
|
69
|
+
}, core.api);
|
|
48
70
|
Object.defineProperty(api, hotUpdaterCoreMetadata, {
|
|
49
71
|
enumerable: false,
|
|
50
72
|
value: {
|
|
@@ -1,25 +1,57 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { AnalyticsProvider } from "./analytics/types.cjs";
|
|
2
|
+
import { ApiKeyManagementAPI } from "./apiKeys.cjs";
|
|
3
|
+
import { HotUpdaterHandlers } from "./handlerTypes.cjs";
|
|
4
|
+
import { DatabaseAPI, DatabasePlugin as DatabasePlugin$1 } from "./db/types.cjs";
|
|
5
|
+
import { StoragePlugin } from "@hot-updater/plugin-core";
|
|
4
6
|
|
|
5
7
|
//#region src/createHotUpdaterCore.d.ts
|
|
6
|
-
type RuntimeHotUpdaterAPI
|
|
7
|
-
readonly
|
|
8
|
-
readonly handler: (request: Request, context?: HotUpdaterContext<TContext>) => Promise<Response>;
|
|
8
|
+
type RuntimeHotUpdaterAPI = DatabaseAPI & {
|
|
9
|
+
readonly handlers: HotUpdaterHandlers;
|
|
9
10
|
readonly adapterName: string;
|
|
11
|
+
/**
|
|
12
|
+
* Built-in Analytics provider. Client ingestion and admin query routes are
|
|
13
|
+
* always mounted; React Native clients independently opt into lifecycle
|
|
14
|
+
* reporting with `HotUpdater.init({ analytics: true })`.
|
|
15
|
+
*/
|
|
16
|
+
readonly analytics: AnalyticsProvider;
|
|
17
|
+
/**
|
|
18
|
+
* In-process API key lifecycle operations for trusted server tooling.
|
|
19
|
+
* Creation returns the plaintext once; list and revoke expose only metadata.
|
|
20
|
+
* This capability is never mounted on the client or admin HTTP handlers.
|
|
21
|
+
*/
|
|
22
|
+
readonly apiKeys: ApiKeyManagementAPI;
|
|
23
|
+
};
|
|
24
|
+
type HotUpdaterAPI = RuntimeHotUpdaterAPI;
|
|
25
|
+
type ClientAccessPolicy = {
|
|
26
|
+
/**
|
|
27
|
+
* Leaves Release Catalog, artifact, and Analytics ingestion routes
|
|
28
|
+
* publicly accessible without a client credential.
|
|
29
|
+
*/
|
|
30
|
+
readonly type: "public";
|
|
31
|
+
} | {
|
|
32
|
+
/**
|
|
33
|
+
* Requires a key registered in `database.models.apiKeys` for
|
|
34
|
+
* Release Catalog, artifact, and Analytics ingestion requests.
|
|
35
|
+
*/
|
|
36
|
+
readonly type: "api-key";
|
|
37
|
+
/**
|
|
38
|
+
* Request header containing the API key. Defaults to
|
|
39
|
+
* `x-api-key`. Clients must send the same header; Release Catalog
|
|
40
|
+
* responses include it in `Vary` to preserve cache isolation.
|
|
41
|
+
*/
|
|
42
|
+
readonly headerName?: string;
|
|
10
43
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
readonly database: DatabaseAdapter<TContext>;
|
|
14
|
-
readonly storages?: readonly (RuntimeStoragePlugin<TContext> | StoragePluginFactory<TContext>)[];
|
|
44
|
+
interface CreateHotUpdaterOptions {
|
|
45
|
+
readonly database: DatabasePlugin$1;
|
|
15
46
|
/**
|
|
16
|
-
*
|
|
47
|
+
* Required client-route access policy. This choice is explicit so a server
|
|
48
|
+
* cannot accidentally change between public and authenticated OTA access.
|
|
49
|
+
* `/version`, storage downloads, and admin-handler routes are unaffected.
|
|
17
50
|
*/
|
|
18
|
-
readonly
|
|
19
|
-
|
|
20
|
-
readonly
|
|
21
|
-
readonly routes?: HandlerRoutes;
|
|
51
|
+
readonly clientAccess: ClientAccessPolicy;
|
|
52
|
+
/** Storage implementations used to read provider-specific storage URIs. */
|
|
53
|
+
readonly storage?: readonly StoragePlugin[];
|
|
22
54
|
}
|
|
23
|
-
declare function createHotUpdater
|
|
55
|
+
declare function createHotUpdater(options: CreateHotUpdaterOptions): RuntimeHotUpdaterAPI;
|
|
24
56
|
//#endregion
|
|
25
|
-
export { CreateHotUpdaterOptions, HotUpdaterAPI, RuntimeHotUpdaterAPI, createHotUpdater };
|
|
57
|
+
export { ClientAccessPolicy, CreateHotUpdaterOptions, HotUpdaterAPI, RuntimeHotUpdaterAPI, createHotUpdater };
|
|
@@ -1,25 +1,57 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { AnalyticsProvider } from "./analytics/types.mjs";
|
|
2
|
+
import { ApiKeyManagementAPI } from "./apiKeys.mjs";
|
|
3
|
+
import { HotUpdaterHandlers } from "./handlerTypes.mjs";
|
|
4
|
+
import { DatabaseAPI, DatabasePlugin as DatabasePlugin$1 } from "./db/types.mjs";
|
|
5
|
+
import { StoragePlugin } from "@hot-updater/plugin-core";
|
|
4
6
|
|
|
5
7
|
//#region src/createHotUpdaterCore.d.ts
|
|
6
|
-
type RuntimeHotUpdaterAPI
|
|
7
|
-
readonly
|
|
8
|
-
readonly handler: (request: Request, context?: HotUpdaterContext<TContext>) => Promise<Response>;
|
|
8
|
+
type RuntimeHotUpdaterAPI = DatabaseAPI & {
|
|
9
|
+
readonly handlers: HotUpdaterHandlers;
|
|
9
10
|
readonly adapterName: string;
|
|
11
|
+
/**
|
|
12
|
+
* Built-in Analytics provider. Client ingestion and admin query routes are
|
|
13
|
+
* always mounted; React Native clients independently opt into lifecycle
|
|
14
|
+
* reporting with `HotUpdater.init({ analytics: true })`.
|
|
15
|
+
*/
|
|
16
|
+
readonly analytics: AnalyticsProvider;
|
|
17
|
+
/**
|
|
18
|
+
* In-process API key lifecycle operations for trusted server tooling.
|
|
19
|
+
* Creation returns the plaintext once; list and revoke expose only metadata.
|
|
20
|
+
* This capability is never mounted on the client or admin HTTP handlers.
|
|
21
|
+
*/
|
|
22
|
+
readonly apiKeys: ApiKeyManagementAPI;
|
|
23
|
+
};
|
|
24
|
+
type HotUpdaterAPI = RuntimeHotUpdaterAPI;
|
|
25
|
+
type ClientAccessPolicy = {
|
|
26
|
+
/**
|
|
27
|
+
* Leaves Release Catalog, artifact, and Analytics ingestion routes
|
|
28
|
+
* publicly accessible without a client credential.
|
|
29
|
+
*/
|
|
30
|
+
readonly type: "public";
|
|
31
|
+
} | {
|
|
32
|
+
/**
|
|
33
|
+
* Requires a key registered in `database.models.apiKeys` for
|
|
34
|
+
* Release Catalog, artifact, and Analytics ingestion requests.
|
|
35
|
+
*/
|
|
36
|
+
readonly type: "api-key";
|
|
37
|
+
/**
|
|
38
|
+
* Request header containing the API key. Defaults to
|
|
39
|
+
* `x-api-key`. Clients must send the same header; Release Catalog
|
|
40
|
+
* responses include it in `Vary` to preserve cache isolation.
|
|
41
|
+
*/
|
|
42
|
+
readonly headerName?: string;
|
|
10
43
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
readonly database: DatabaseAdapter<TContext>;
|
|
14
|
-
readonly storages?: readonly (RuntimeStoragePlugin<TContext> | StoragePluginFactory<TContext>)[];
|
|
44
|
+
interface CreateHotUpdaterOptions {
|
|
45
|
+
readonly database: DatabasePlugin$1;
|
|
15
46
|
/**
|
|
16
|
-
*
|
|
47
|
+
* Required client-route access policy. This choice is explicit so a server
|
|
48
|
+
* cannot accidentally change between public and authenticated OTA access.
|
|
49
|
+
* `/version`, storage downloads, and admin-handler routes are unaffected.
|
|
17
50
|
*/
|
|
18
|
-
readonly
|
|
19
|
-
|
|
20
|
-
readonly
|
|
21
|
-
readonly routes?: HandlerRoutes;
|
|
51
|
+
readonly clientAccess: ClientAccessPolicy;
|
|
52
|
+
/** Storage implementations used to read provider-specific storage URIs. */
|
|
53
|
+
readonly storage?: readonly StoragePlugin[];
|
|
22
54
|
}
|
|
23
|
-
declare function createHotUpdater
|
|
55
|
+
declare function createHotUpdater(options: CreateHotUpdaterOptions): RuntimeHotUpdaterAPI;
|
|
24
56
|
//#endregion
|
|
25
|
-
export { CreateHotUpdaterOptions, HotUpdaterAPI, RuntimeHotUpdaterAPI, createHotUpdater };
|
|
57
|
+
export { ClientAccessPolicy, CreateHotUpdaterOptions, HotUpdaterAPI, RuntimeHotUpdaterAPI, createHotUpdater };
|
|
@@ -1,49 +1,71 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createHotUpdaterHandlers } from "./handler.mjs";
|
|
2
|
+
import { createAnalyticsProvider } from "./analytics/bounded/provider.mjs";
|
|
3
|
+
import { authenticateApiKey, createApiKeyManagement, normalizeApiKeyHeaderName } from "./apiKeys.mjs";
|
|
4
|
+
import { createDatabasePluginCore } from "./db/databasePluginCore.mjs";
|
|
3
5
|
import { createSchemaReadinessChecker } from "./db/schemaReadiness.mjs";
|
|
4
|
-
import { isDatabasePlugin
|
|
5
|
-
import { normalizeBasePath } from "./route.mjs";
|
|
6
|
+
import { isDatabasePlugin } from "./db/types.mjs";
|
|
6
7
|
import { createStorageAccess } from "./storageAccess.mjs";
|
|
7
|
-
import {
|
|
8
|
+
import { assertStorageOperations } from "@hot-updater/plugin-core";
|
|
8
9
|
//#region src/createHotUpdaterCore.ts
|
|
10
|
+
const normalizeClientAccess = (value) => {
|
|
11
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new TypeError("clientAccess must be an object.");
|
|
12
|
+
const policy = value;
|
|
13
|
+
if (policy.type === "public") return { type: "public" };
|
|
14
|
+
if (policy.type === "api-key") return {
|
|
15
|
+
headerName: normalizeApiKeyHeaderName(policy.headerName),
|
|
16
|
+
type: "api-key"
|
|
17
|
+
};
|
|
18
|
+
throw new TypeError("clientAccess.type must be either \"public\" or \"api-key\".");
|
|
19
|
+
};
|
|
9
20
|
const hotUpdaterCoreMetadata = Symbol.for("@hot-updater/server/core-metadata");
|
|
10
21
|
function getHotUpdaterCoreMetadata(hotUpdater) {
|
|
11
22
|
return hotUpdater[hotUpdaterCoreMetadata];
|
|
12
23
|
}
|
|
13
24
|
function createHotUpdaterCore(options) {
|
|
25
|
+
for (const key of ["authorityId", "catalogId"]) if (Object.hasOwn(options, key)) throw new TypeError(`Remove ${key} from createHotUpdater options. Catalog identity is managed internally.`);
|
|
14
26
|
const database = options.database;
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
assertRuntimeStoragePlugin(storagePlugin);
|
|
19
|
-
return storagePlugin;
|
|
27
|
+
const { downloadStorageObject, readStorageText, resolveFileUrl } = createStorageAccess((options.storage ?? []).map((storage) => {
|
|
28
|
+
assertStorageOperations(storage, ["get", "getDownloadUrl"]);
|
|
29
|
+
return storage;
|
|
20
30
|
}));
|
|
21
|
-
if (!isDatabasePluginFactory(database) && !isDatabasePlugin(database)) throw new Error("@hot-updater/server only supports database plugins.");
|
|
22
31
|
const adapterCapabilities = database;
|
|
23
|
-
|
|
32
|
+
if (!isDatabasePlugin(database)) throw new Error("@hot-updater/server only supports database plugins.");
|
|
33
|
+
const plugin = database;
|
|
24
34
|
const assertSchemaReady = createSchemaReadinessChecker(adapterCapabilities.adapterName ?? plugin.name, adapterCapabilities.createMigrator);
|
|
25
|
-
const core =
|
|
26
|
-
createMutationPlugin: () => database(),
|
|
27
|
-
beforeOperation: assertSchemaReady,
|
|
28
|
-
readStorageText
|
|
29
|
-
} : {
|
|
35
|
+
const core = createDatabasePluginCore(plugin, resolveFileUrl, {
|
|
30
36
|
beforeOperation: assertSchemaReady,
|
|
31
37
|
readStorageText
|
|
32
38
|
});
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
const clientAccess = normalizeClientAccess(options.clientAccess);
|
|
40
|
+
const analytics = createAnalyticsProvider({
|
|
41
|
+
async append(row) {
|
|
42
|
+
await assertSchemaReady();
|
|
43
|
+
return plugin.models.analytics.append(row);
|
|
44
|
+
},
|
|
45
|
+
async scan(input) {
|
|
46
|
+
await assertSchemaReady();
|
|
47
|
+
return plugin.models.analytics.scan(input);
|
|
48
|
+
}
|
|
36
49
|
});
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
41
|
-
const
|
|
42
|
-
|
|
50
|
+
const apiKeys = createApiKeyManagement({
|
|
51
|
+
apiKeys: plugin.models.apiKeys,
|
|
52
|
+
beforeOperation: assertSchemaReady
|
|
53
|
+
});
|
|
54
|
+
const handlers = createHotUpdaterHandlers(core.api, analytics, clientAccess.type === "api-key" ? {
|
|
55
|
+
authenticate: (request) => authenticateApiKey({
|
|
56
|
+
apiKeys: plugin.models.apiKeys,
|
|
57
|
+
beforeLookup: assertSchemaReady,
|
|
58
|
+
headerName: clientAccess.headerName,
|
|
59
|
+
request
|
|
60
|
+
}),
|
|
61
|
+
headerName: clientAccess.headerName
|
|
62
|
+
} : void 0, downloadStorageObject);
|
|
63
|
+
const api = Object.assign({
|
|
43
64
|
adapterName: adapterCapabilities.adapterName ?? core.adapterName,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
analytics,
|
|
66
|
+
apiKeys,
|
|
67
|
+
handlers
|
|
68
|
+
}, core.api);
|
|
47
69
|
Object.defineProperty(api, hotUpdaterCoreMetadata, {
|
|
48
70
|
enumerable: false,
|
|
49
71
|
value: {
|
|
@@ -3,10 +3,6 @@ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
|
3
3
|
let _hot_updater_core = require("@hot-updater/core");
|
|
4
4
|
let node_crypto = require("node:crypto");
|
|
5
5
|
node_crypto = require_runtime.__toESM(node_crypto);
|
|
6
|
-
let node_fs_promises = require("node:fs/promises");
|
|
7
|
-
node_fs_promises = require_runtime.__toESM(node_fs_promises);
|
|
8
|
-
let node_os = require("node:os");
|
|
9
|
-
node_os = require_runtime.__toESM(node_os);
|
|
10
6
|
let node_path = require("node:path");
|
|
11
7
|
node_path = require_runtime.__toESM(node_path);
|
|
12
8
|
let node_util = require("node:util");
|
|
@@ -14,7 +10,6 @@ let node_zlib = require("node:zlib");
|
|
|
14
10
|
let _hot_updater_bsdiff = require("@hot-updater/bsdiff");
|
|
15
11
|
//#region src/db/createBundleDiff.ts
|
|
16
12
|
const HBC_ASSET_PATH_RE = /\.bundle$/;
|
|
17
|
-
const HOT_UPDATER_DOWNLOAD_DIR_PREFIX = "downloads-";
|
|
18
13
|
const decompressBrotli = (0, node_util.promisify)(node_zlib.brotliDecompress);
|
|
19
14
|
const isBundleManifest = (value) => {
|
|
20
15
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
@@ -39,23 +34,14 @@ async function downloadFromUrl(url) {
|
|
|
39
34
|
}
|
|
40
35
|
async function downloadStorageBytes(storageUri, storagePlugin) {
|
|
41
36
|
const protocol = new URL(storageUri).protocol.replace(":", "");
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
await node_fs_promises.default.mkdir(downloadRoot, { recursive: true });
|
|
47
|
-
const workDir = await node_fs_promises.default.mkdtemp(node_path.default.join(downloadRoot, HOT_UPDATER_DOWNLOAD_DIR_PREFIX));
|
|
48
|
-
const filename = node_path.default.basename(new URL(storageUri).pathname) || (0, node_crypto.randomUUID)();
|
|
49
|
-
const filePath = node_path.default.join(workDir, filename);
|
|
50
|
-
try {
|
|
51
|
-
await storagePlugin.profiles.node.downloadFile(storageUri, filePath);
|
|
52
|
-
return new Uint8Array(await node_fs_promises.default.readFile(filePath));
|
|
53
|
-
} finally {
|
|
54
|
-
await node_fs_promises.default.rm(workDir, {
|
|
55
|
-
force: true,
|
|
56
|
-
recursive: true
|
|
57
|
-
});
|
|
37
|
+
if (!storagePlugin || storagePlugin.protocol !== protocol) {
|
|
38
|
+
if (protocol === "http" || protocol === "https") return downloadFromUrl(storageUri);
|
|
39
|
+
if (!storagePlugin) throw new Error("Storage plugin is not configured");
|
|
40
|
+
throw new Error(`No storage plugin for protocol: ${protocol}`);
|
|
58
41
|
}
|
|
42
|
+
const { response } = await storagePlugin.get({ storageUri });
|
|
43
|
+
if (response === null) throw new Error(`Storage object not found: ${storageUri}`);
|
|
44
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
59
45
|
}
|
|
60
46
|
async function fetchManifest(bundle, storagePlugin) {
|
|
61
47
|
const manifestStorageUri = (0, _hot_updater_core.getManifestStorageUri)(bundle);
|
|
@@ -81,12 +67,16 @@ async function fetchAssetBytes(bundle, assetPath, manifest, storagePlugin) {
|
|
|
81
67
|
const compressedAssetStorageUri = (0, _hot_updater_plugin_core.resolveManifestAssetStorageUri)({
|
|
82
68
|
assetBaseStorageUri,
|
|
83
69
|
assetPath: downloadPath,
|
|
70
|
+
downloadFileHash: asset.downloadFileHash,
|
|
84
71
|
fileHash: asset.fileHash
|
|
85
72
|
});
|
|
86
73
|
let compressedBytes = null;
|
|
87
74
|
try {
|
|
88
75
|
compressedBytes = await downloadStorageBytes(compressedAssetStorageUri, storagePlugin);
|
|
89
|
-
} catch {
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (!(error instanceof Error)) throw error;
|
|
78
|
+
compressedBytes = null;
|
|
79
|
+
}
|
|
90
80
|
if (compressedBytes) return new Uint8Array(await decompressBrotli(compressedBytes));
|
|
91
81
|
}
|
|
92
82
|
return downloadStorageBytes((0, _hot_updater_plugin_core.resolveManifestAssetStorageUri)({
|
|
@@ -95,23 +85,16 @@ async function fetchAssetBytes(bundle, assetPath, manifest, storagePlugin) {
|
|
|
95
85
|
fileHash: asset.fileHash
|
|
96
86
|
}), storagePlugin);
|
|
97
87
|
}
|
|
98
|
-
async function getFileHash(filePath) {
|
|
99
|
-
const file = await node_fs_promises.default.readFile(filePath);
|
|
100
|
-
return node_crypto.default.createHash("sha256").update(file).digest("hex");
|
|
101
|
-
}
|
|
102
88
|
function buildNextPatchState({ currentBundle, nextPatch, makePrimary }) {
|
|
103
89
|
const existingPatches = (0, _hot_updater_core.getBundlePatches)(currentBundle).filter((patch) => patch.baseBundleId !== nextPatch.baseBundleId);
|
|
104
|
-
|
|
105
|
-
return {
|
|
106
|
-
patches: orderedPatches,
|
|
107
|
-
primaryPatch: orderedPatches[0] ?? nextPatch
|
|
108
|
-
};
|
|
90
|
+
return makePrimary ? [nextPatch, ...existingPatches] : [...existingPatches, nextPatch];
|
|
109
91
|
}
|
|
110
92
|
async function createBundleDiff({ baseBundleId, bundleId }, deps, options = {}) {
|
|
93
|
+
const database = (0, _hot_updater_plugin_core.createDatabaseClient)(deps.databasePlugin);
|
|
111
94
|
if (!deps.storagePlugin) throw new Error("Storage plugin is not configured");
|
|
112
95
|
if (baseBundleId === bundleId) throw new Error("Base bundle must be different from the target bundle");
|
|
113
|
-
const baseBundle = await
|
|
114
|
-
const targetBundle = await
|
|
96
|
+
const baseBundle = await database.getBundleById(baseBundleId);
|
|
97
|
+
const targetBundle = await database.getBundleById(bundleId);
|
|
115
98
|
if (!baseBundle || !targetBundle) throw new Error("Bundle not found");
|
|
116
99
|
if (baseBundle.platform !== targetBundle.platform) throw new Error("Base bundle platform must match the target bundle");
|
|
117
100
|
if (baseBundle.id.localeCompare(targetBundle.id) >= 0) throw new Error("Base bundle must be older than the target bundle");
|
|
@@ -125,43 +108,37 @@ async function createBundleDiff({ baseBundleId, bundleId }, deps, options = {})
|
|
|
125
108
|
if (baseAssetHash === targetAssetHash) throw new Error("Hermes bundle is unchanged; no diff patch is required");
|
|
126
109
|
const [baseBytes, targetBytes] = await Promise.all([fetchAssetBytes(baseBundle, baseAssetPath, baseManifest, deps.storagePlugin), fetchAssetBytes(targetBundle, targetAssetPath, targetManifest, deps.storagePlugin)]);
|
|
127
110
|
const patchBytes = await (0, _hot_updater_bsdiff.hdiff)(baseBytes, targetBytes);
|
|
128
|
-
const
|
|
111
|
+
const patchFileHash = node_crypto.default.createHash("sha256").update(patchBytes).digest("hex");
|
|
129
112
|
const patchFilename = `${node_path.default.posix.basename(targetAssetPath)}.bsdiff`;
|
|
130
|
-
const patchPath = node_path.default.join(workDir, patchFilename);
|
|
131
113
|
const previousPatch = (0, _hot_updater_core.getBundlePatch)(targetBundle, baseBundle.id);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
await node_fs_promises.default.rm(workDir, {
|
|
161
|
-
force: true,
|
|
162
|
-
recursive: true
|
|
163
|
-
});
|
|
164
|
-
}
|
|
114
|
+
const uploadKey = (0, _hot_updater_plugin_core.createBundleStorageKey)(targetBundle.id, "patches", baseBundle.id, patchFileHash, getRelativeStorageDir(targetAssetPath), patchFilename);
|
|
115
|
+
const patchUpload = await deps.storagePlugin.put({
|
|
116
|
+
key: uploadKey,
|
|
117
|
+
body: new ReadableStream({ start(controller) {
|
|
118
|
+
controller.enqueue(patchBytes);
|
|
119
|
+
controller.close();
|
|
120
|
+
} }),
|
|
121
|
+
contentLength: patchBytes.byteLength,
|
|
122
|
+
contentType: "application/octet-stream"
|
|
123
|
+
});
|
|
124
|
+
const patches = buildNextPatchState({
|
|
125
|
+
currentBundle: targetBundle,
|
|
126
|
+
nextPatch: {
|
|
127
|
+
baseBundleId: baseBundle.id,
|
|
128
|
+
baseFileHash: baseAssetHash,
|
|
129
|
+
byteSize: patchBytes.byteLength,
|
|
130
|
+
patchFileHash,
|
|
131
|
+
patchStorageUri: patchUpload.storageUri
|
|
132
|
+
},
|
|
133
|
+
makePrimary: options.makePrimary ?? true
|
|
134
|
+
});
|
|
135
|
+
const updatedBundle = {
|
|
136
|
+
...targetBundle,
|
|
137
|
+
patches
|
|
138
|
+
};
|
|
139
|
+
await database.updateBundleById(targetBundle.id, updatedBundle);
|
|
140
|
+
if (previousPatch?.patchStorageUri && previousPatch.patchStorageUri !== patchUpload.storageUri) await deps.storagePlugin.delete({ storageUri: previousPatch.patchStorageUri }).catch(() => {});
|
|
141
|
+
return updatedBundle;
|
|
165
142
|
}
|
|
166
143
|
//#endregion
|
|
167
144
|
exports.createBundleDiff = createBundleDiff;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Bundle,
|
|
1
|
+
import { Bundle, BundleRepository, StoragePluginWith } from "@hot-updater/plugin-core";
|
|
2
2
|
|
|
3
3
|
//#region src/db/createBundleDiff.d.ts
|
|
4
4
|
interface CreateBundleDiffInput {
|
|
@@ -6,8 +6,8 @@ interface CreateBundleDiffInput {
|
|
|
6
6
|
bundleId: string;
|
|
7
7
|
}
|
|
8
8
|
interface CreateBundleDiffDependencies {
|
|
9
|
-
databasePlugin:
|
|
10
|
-
storagePlugin:
|
|
9
|
+
databasePlugin: BundleRepository;
|
|
10
|
+
storagePlugin: StoragePluginWith<"get" | "put" | "delete"> | null;
|
|
11
11
|
}
|
|
12
12
|
interface CreateBundleDiffOptions {
|
|
13
13
|
makePrimary?: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Bundle,
|
|
1
|
+
import { Bundle, BundleRepository, StoragePluginWith } from "@hot-updater/plugin-core";
|
|
2
2
|
|
|
3
3
|
//#region src/db/createBundleDiff.d.ts
|
|
4
4
|
interface CreateBundleDiffInput {
|
|
@@ -6,8 +6,8 @@ interface CreateBundleDiffInput {
|
|
|
6
6
|
bundleId: string;
|
|
7
7
|
}
|
|
8
8
|
interface CreateBundleDiffDependencies {
|
|
9
|
-
databasePlugin:
|
|
10
|
-
storagePlugin:
|
|
9
|
+
databasePlugin: BundleRepository;
|
|
10
|
+
storagePlugin: StoragePluginWith<"get" | "put" | "delete"> | null;
|
|
11
11
|
}
|
|
12
12
|
interface CreateBundleDiffOptions {
|
|
13
13
|
makePrimary?: boolean;
|