@hot-updater/server 0.35.12 → 0.36.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/db/createBundleDiff.cjs +4 -9
- package/dist/db/createBundleDiff.mjs +5 -10
- package/dist/db/updateArtifacts.cjs +3 -3
- package/dist/db/updateArtifacts.mjs +4 -4
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/package.json +7 -7
- package/src/db/createBundleDiff.spec.ts +2 -2
- package/src/db/createBundleDiff.ts +10 -8
- package/src/db/updateArtifacts.ts +3 -3
|
@@ -14,7 +14,6 @@ let node_zlib = require("node:zlib");
|
|
|
14
14
|
let _hot_updater_bsdiff = require("@hot-updater/bsdiff");
|
|
15
15
|
//#region src/db/createBundleDiff.ts
|
|
16
16
|
const HBC_ASSET_PATH_RE = /\.bundle$/;
|
|
17
|
-
const BR_COMPRESSED_ASSET_PATH_RE = /(^|\/)index\.[^/]+\.bundle$/;
|
|
18
17
|
const HOT_UPDATER_DOWNLOAD_DIR_PREFIX = "downloads-";
|
|
19
18
|
const decompressBrotli = (0, node_util.promisify)(node_zlib.brotliDecompress);
|
|
20
19
|
const isBundleManifest = (value) => {
|
|
@@ -77,10 +76,11 @@ async function fetchAssetBytes(bundle, assetPath, manifest, storagePlugin) {
|
|
|
77
76
|
if (!assetBaseStorageUri) throw new Error(`Bundle ${bundle.id} does not have asset storage metadata`);
|
|
78
77
|
const asset = manifest.assets[assetPath];
|
|
79
78
|
if (!asset) throw new Error(`Asset ${assetPath} is missing from manifest`);
|
|
80
|
-
|
|
79
|
+
const downloadPath = (0, _hot_updater_plugin_core.getManifestAssetDownloadPath)(assetPath);
|
|
80
|
+
if (downloadPath !== assetPath) {
|
|
81
81
|
const compressedAssetStorageUri = (0, _hot_updater_plugin_core.resolveManifestAssetStorageUri)({
|
|
82
82
|
assetBaseStorageUri,
|
|
83
|
-
assetPath:
|
|
83
|
+
assetPath: downloadPath,
|
|
84
84
|
fileHash: asset.fileHash
|
|
85
85
|
});
|
|
86
86
|
let compressedBytes = null;
|
|
@@ -131,12 +131,7 @@ async function createBundleDiff({ baseBundleId, bundleId }, deps, options = {})
|
|
|
131
131
|
const previousPatch = (0, _hot_updater_core.getBundlePatch)(targetBundle, baseBundle.id);
|
|
132
132
|
try {
|
|
133
133
|
await node_fs_promises.default.writeFile(patchPath, patchBytes);
|
|
134
|
-
const uploadKey =
|
|
135
|
-
targetBundle.id,
|
|
136
|
-
"patches",
|
|
137
|
-
baseBundle.id,
|
|
138
|
-
getRelativeStorageDir(targetAssetPath)
|
|
139
|
-
].filter(Boolean).join("/");
|
|
134
|
+
const uploadKey = (0, _hot_updater_plugin_core.createBundleStorageKey)(targetBundle.id, "patches", baseBundle.id, getRelativeStorageDir(targetAssetPath));
|
|
140
135
|
const patchUpload = await deps.storagePlugin.profiles.node.upload(uploadKey, patchPath);
|
|
141
136
|
const patchFileHash = await getFileHash(patchPath);
|
|
142
137
|
const nextState = buildNextPatchState({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolveManifestAssetStorageUri } from "@hot-updater/plugin-core";
|
|
1
|
+
import { createBundleStorageKey, getManifestAssetDownloadPath, resolveManifestAssetStorageUri } from "@hot-updater/plugin-core";
|
|
2
2
|
import { getAssetBaseStorageUri, getBundlePatch, getBundlePatches, getManifestStorageUri } from "@hot-updater/core";
|
|
3
3
|
import crypto, { randomUUID } from "node:crypto";
|
|
4
4
|
import fs from "node:fs/promises";
|
|
@@ -9,7 +9,6 @@ import { brotliDecompress } from "node:zlib";
|
|
|
9
9
|
import { hdiff } from "@hot-updater/bsdiff";
|
|
10
10
|
//#region src/db/createBundleDiff.ts
|
|
11
11
|
const HBC_ASSET_PATH_RE = /\.bundle$/;
|
|
12
|
-
const BR_COMPRESSED_ASSET_PATH_RE = /(^|\/)index\.[^/]+\.bundle$/;
|
|
13
12
|
const HOT_UPDATER_DOWNLOAD_DIR_PREFIX = "downloads-";
|
|
14
13
|
const decompressBrotli = promisify(brotliDecompress);
|
|
15
14
|
const isBundleManifest = (value) => {
|
|
@@ -72,10 +71,11 @@ async function fetchAssetBytes(bundle, assetPath, manifest, storagePlugin) {
|
|
|
72
71
|
if (!assetBaseStorageUri) throw new Error(`Bundle ${bundle.id} does not have asset storage metadata`);
|
|
73
72
|
const asset = manifest.assets[assetPath];
|
|
74
73
|
if (!asset) throw new Error(`Asset ${assetPath} is missing from manifest`);
|
|
75
|
-
|
|
74
|
+
const downloadPath = getManifestAssetDownloadPath(assetPath);
|
|
75
|
+
if (downloadPath !== assetPath) {
|
|
76
76
|
const compressedAssetStorageUri = resolveManifestAssetStorageUri({
|
|
77
77
|
assetBaseStorageUri,
|
|
78
|
-
assetPath:
|
|
78
|
+
assetPath: downloadPath,
|
|
79
79
|
fileHash: asset.fileHash
|
|
80
80
|
});
|
|
81
81
|
let compressedBytes = null;
|
|
@@ -126,12 +126,7 @@ async function createBundleDiff({ baseBundleId, bundleId }, deps, options = {})
|
|
|
126
126
|
const previousPatch = getBundlePatch(targetBundle, baseBundle.id);
|
|
127
127
|
try {
|
|
128
128
|
await fs.writeFile(patchPath, patchBytes);
|
|
129
|
-
const uploadKey =
|
|
130
|
-
targetBundle.id,
|
|
131
|
-
"patches",
|
|
132
|
-
baseBundle.id,
|
|
133
|
-
getRelativeStorageDir(targetAssetPath)
|
|
134
|
-
].filter(Boolean).join("/");
|
|
129
|
+
const uploadKey = createBundleStorageKey(targetBundle.id, "patches", baseBundle.id, getRelativeStorageDir(targetAssetPath));
|
|
135
130
|
const patchUpload = await deps.storagePlugin.profiles.node.upload(uploadKey, patchPath);
|
|
136
131
|
const patchFileHash = await getFileHash(patchPath);
|
|
137
132
|
const nextState = buildNextPatchState({
|
|
@@ -3,7 +3,6 @@ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
|
3
3
|
let _hot_updater_core = require("@hot-updater/core");
|
|
4
4
|
//#region src/db/updateArtifacts.ts
|
|
5
5
|
const HBC_ASSET_PATH_RE = /\.bundle$/;
|
|
6
|
-
const BR_COMPRESSED_ASSET_PATH_RE = /(^|\/)index\.[^/]+\.bundle$/;
|
|
7
6
|
const resolveUniqueHbcAssetPath = (manifest) => {
|
|
8
7
|
const candidates = Object.keys(manifest.assets).sort((left, right) => left.localeCompare(right)).filter((candidate) => HBC_ASSET_PATH_RE.test(candidate));
|
|
9
8
|
return candidates.length === 1 ? candidates[0] : null;
|
|
@@ -56,10 +55,11 @@ async function resolveChangedAssets({ assetBaseStorageUri, currentManifest, curr
|
|
|
56
55
|
});
|
|
57
56
|
const changedEntries = await Promise.all(Object.entries(targetManifest.assets).map(async ([assetPath, asset]) => {
|
|
58
57
|
if ((currentManifest?.assets[assetPath])?.fileHash === asset.fileHash) return null;
|
|
59
|
-
const
|
|
58
|
+
const downloadPath = (0, _hot_updater_plugin_core.getManifestAssetDownloadPath)(assetPath);
|
|
59
|
+
const usesBrotliAsset = downloadPath !== assetPath;
|
|
60
60
|
const storageUri = (0, _hot_updater_plugin_core.resolveManifestAssetStorageUri)({
|
|
61
61
|
assetBaseStorageUri,
|
|
62
|
-
assetPath:
|
|
62
|
+
assetPath: downloadPath,
|
|
63
63
|
fileHash: asset.fileHash
|
|
64
64
|
});
|
|
65
65
|
const patch = patchDescriptor?.assetPath === assetPath ? patchDescriptor.patch : null;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { resolveManifestAssetStorageUri } from "@hot-updater/plugin-core";
|
|
1
|
+
import { getManifestAssetDownloadPath, resolveManifestAssetStorageUri } from "@hot-updater/plugin-core";
|
|
2
2
|
import { getAssetBaseStorageUri, getBundlePatch, getManifestFileHash, getManifestStorageUri, stripBundleArtifactMetadata } from "@hot-updater/core";
|
|
3
3
|
//#region src/db/updateArtifacts.ts
|
|
4
4
|
const HBC_ASSET_PATH_RE = /\.bundle$/;
|
|
5
|
-
const BR_COMPRESSED_ASSET_PATH_RE = /(^|\/)index\.[^/]+\.bundle$/;
|
|
6
5
|
const resolveUniqueHbcAssetPath = (manifest) => {
|
|
7
6
|
const candidates = Object.keys(manifest.assets).sort((left, right) => left.localeCompare(right)).filter((candidate) => HBC_ASSET_PATH_RE.test(candidate));
|
|
8
7
|
return candidates.length === 1 ? candidates[0] : null;
|
|
@@ -55,10 +54,11 @@ async function resolveChangedAssets({ assetBaseStorageUri, currentManifest, curr
|
|
|
55
54
|
});
|
|
56
55
|
const changedEntries = await Promise.all(Object.entries(targetManifest.assets).map(async ([assetPath, asset]) => {
|
|
57
56
|
if ((currentManifest?.assets[assetPath])?.fileHash === asset.fileHash) return null;
|
|
58
|
-
const
|
|
57
|
+
const downloadPath = getManifestAssetDownloadPath(assetPath);
|
|
58
|
+
const usesBrotliAsset = downloadPath !== assetPath;
|
|
59
59
|
const storageUri = resolveManifestAssetStorageUri({
|
|
60
60
|
assetBaseStorageUri,
|
|
61
|
-
assetPath:
|
|
61
|
+
assetPath: downloadPath,
|
|
62
62
|
fileHash: asset.fileHash
|
|
63
63
|
});
|
|
64
64
|
const patch = patchDescriptor?.assetPath === assetPath ? patchDescriptor.patch : null;
|
package/dist/package.cjs
CHANGED
package/dist/package.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "React Native OTA solution for self-hosted",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -55,10 +55,10 @@
|
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"rou3": "0.7.9",
|
|
57
57
|
"verkit": "0.3.2",
|
|
58
|
-
"@hot-updater/
|
|
59
|
-
"@hot-updater/
|
|
60
|
-
"@hot-updater/plugin-core": "0.
|
|
61
|
-
"@hot-updater/
|
|
58
|
+
"@hot-updater/js": "0.36.0",
|
|
59
|
+
"@hot-updater/bsdiff": "0.36.0",
|
|
60
|
+
"@hot-updater/plugin-core": "0.36.0",
|
|
61
|
+
"@hot-updater/core": "0.36.0"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"@prisma/client": "*",
|
|
@@ -90,8 +90,8 @@
|
|
|
90
90
|
"mongodb": "6.20.0",
|
|
91
91
|
"msw": "^2.7.0",
|
|
92
92
|
"uuidv7": "^1.0.2",
|
|
93
|
-
"@hot-updater/standalone": "0.
|
|
94
|
-
"@hot-updater/test-utils": "0.
|
|
93
|
+
"@hot-updater/standalone": "0.36.0",
|
|
94
|
+
"@hot-updater/test-utils": "0.36.0"
|
|
95
95
|
},
|
|
96
96
|
"scripts": {
|
|
97
97
|
"build": "tsdown",
|
|
@@ -193,7 +193,7 @@ describe("createBundleDiff", () => {
|
|
|
193
193
|
});
|
|
194
194
|
expect(updatedBundle.patchFileHash).toMatch(/[a-f0-9]{64}/);
|
|
195
195
|
expect(updatedBundle.patchStorageUri).toContain(
|
|
196
|
-
|
|
196
|
+
`bundles/${targetBundle.id}/patches/${baseBundle.id}`,
|
|
197
197
|
);
|
|
198
198
|
expect(updatedBundle.patches).toEqual([
|
|
199
199
|
{
|
|
@@ -394,7 +394,7 @@ describe("createBundleDiff", () => {
|
|
|
394
394
|
baseFileHash: "hash-secondary-old",
|
|
395
395
|
patchFileHash: expect.any(String),
|
|
396
396
|
patchStorageUri: expect.stringContaining(
|
|
397
|
-
|
|
397
|
+
`bundles/${targetBundle.id}/patches/${secondaryBaseBundle.id}`,
|
|
398
398
|
),
|
|
399
399
|
},
|
|
400
400
|
]);
|
|
@@ -17,7 +17,11 @@ import type {
|
|
|
17
17
|
DatabasePlugin,
|
|
18
18
|
NodeStoragePlugin,
|
|
19
19
|
} from "@hot-updater/plugin-core";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
createBundleStorageKey,
|
|
22
|
+
getManifestAssetDownloadPath,
|
|
23
|
+
resolveManifestAssetStorageUri,
|
|
24
|
+
} from "@hot-updater/plugin-core";
|
|
21
25
|
|
|
22
26
|
type BundleManifest = {
|
|
23
27
|
bundleId: string;
|
|
@@ -39,7 +43,6 @@ export interface CreateBundleDiffOptions {
|
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
const HBC_ASSET_PATH_RE = /\.bundle$/;
|
|
42
|
-
const BR_COMPRESSED_ASSET_PATH_RE = /(^|\/)index\.[^/]+\.bundle$/;
|
|
43
46
|
const HOT_UPDATER_DOWNLOAD_DIR_PREFIX = "downloads-";
|
|
44
47
|
const decompressBrotli = promisify(brotliDecompress);
|
|
45
48
|
|
|
@@ -186,10 +189,11 @@ async function fetchAssetBytes(
|
|
|
186
189
|
throw new Error(`Asset ${assetPath} is missing from manifest`);
|
|
187
190
|
}
|
|
188
191
|
|
|
189
|
-
|
|
192
|
+
const downloadPath = getManifestAssetDownloadPath(assetPath);
|
|
193
|
+
if (downloadPath !== assetPath) {
|
|
190
194
|
const compressedAssetStorageUri = resolveManifestAssetStorageUri({
|
|
191
195
|
assetBaseStorageUri,
|
|
192
|
-
assetPath:
|
|
196
|
+
assetPath: downloadPath,
|
|
193
197
|
fileHash: asset.fileHash,
|
|
194
198
|
});
|
|
195
199
|
|
|
@@ -321,14 +325,12 @@ export async function createBundleDiff(
|
|
|
321
325
|
try {
|
|
322
326
|
await fs.writeFile(patchPath, patchBytes);
|
|
323
327
|
|
|
324
|
-
const uploadKey =
|
|
328
|
+
const uploadKey = createBundleStorageKey(
|
|
325
329
|
targetBundle.id,
|
|
326
330
|
"patches",
|
|
327
331
|
baseBundle.id,
|
|
328
332
|
getRelativeStorageDir(targetAssetPath),
|
|
329
|
-
|
|
330
|
-
.filter(Boolean)
|
|
331
|
-
.join("/");
|
|
333
|
+
);
|
|
332
334
|
const patchUpload = await deps.storagePlugin.profiles.node.upload(
|
|
333
335
|
uploadKey,
|
|
334
336
|
patchPath,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type ChangedAsset,
|
|
10
10
|
} from "@hot-updater/core";
|
|
11
11
|
import {
|
|
12
|
+
getManifestAssetDownloadPath,
|
|
12
13
|
resolveManifestAssetStorageUri,
|
|
13
14
|
type HotUpdaterContext,
|
|
14
15
|
} from "@hot-updater/plugin-core";
|
|
@@ -29,7 +30,6 @@ type ReadStorageText<TContext> = (
|
|
|
29
30
|
) => Promise<string | null>;
|
|
30
31
|
|
|
31
32
|
const HBC_ASSET_PATH_RE = /\.bundle$/;
|
|
32
|
-
const BR_COMPRESSED_ASSET_PATH_RE = /(^|\/)index\.[^/]+\.bundle$/;
|
|
33
33
|
|
|
34
34
|
const resolveUniqueHbcAssetPath = (manifest: BundleManifest) => {
|
|
35
35
|
const candidates = Object.keys(manifest.assets)
|
|
@@ -199,8 +199,8 @@ async function resolveChangedAssets<TContext>({
|
|
|
199
199
|
return null;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
const
|
|
203
|
-
const
|
|
202
|
+
const downloadPath = getManifestAssetDownloadPath(assetPath);
|
|
203
|
+
const usesBrotliAsset = downloadPath !== assetPath;
|
|
204
204
|
const storageUri = resolveManifestAssetStorageUri({
|
|
205
205
|
assetBaseStorageUri,
|
|
206
206
|
assetPath: downloadPath,
|