@hot-updater/vercel 1.0.5 → 1.0.7
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/function/index.mjs +134 -4
- package/package.json +7 -7
package/dist/function/index.mjs
CHANGED
|
@@ -17558,7 +17558,7 @@ const postgres = (config) => {
|
|
|
17558
17558
|
};
|
|
17559
17559
|
//#endregion
|
|
17560
17560
|
//#region ../../packages/server/dist/version.mjs
|
|
17561
|
-
const HOT_UPDATER_SERVER_VERSION = "1.0.
|
|
17561
|
+
const HOT_UPDATER_SERVER_VERSION = "1.0.7";
|
|
17562
17562
|
//#endregion
|
|
17563
17563
|
//#region ../../packages/server/dist/handlerVersionRoutes.mjs
|
|
17564
17564
|
const createVersionRouteHandlers = (plugins = []) => {
|
|
@@ -17847,6 +17847,85 @@ async function resolveManifestArtifacts({ currentBundle, resolveFileUrl, readSto
|
|
|
17847
17847
|
...archiveUrl ? { archiveUrl } : {}
|
|
17848
17848
|
};
|
|
17849
17849
|
}
|
|
17850
|
+
async function loadTargetPlan({ currentBundle, readStorageText, targetBundle }) {
|
|
17851
|
+
const manifestStorageUri = getManifestStorageUri(targetBundle);
|
|
17852
|
+
const manifestFileHash = getManifestFileHash(targetBundle);
|
|
17853
|
+
const assetBaseStorageUri = getAssetBaseStorageUri(targetBundle);
|
|
17854
|
+
if (!manifestStorageUri || !manifestFileHash || !assetBaseStorageUri) return null;
|
|
17855
|
+
const targetManifest = await fetchBundleManifest(manifestStorageUri, readStorageText);
|
|
17856
|
+
if (!targetManifest) return null;
|
|
17857
|
+
return {
|
|
17858
|
+
manifestFileHash,
|
|
17859
|
+
manifestStorageUri,
|
|
17860
|
+
plan: createManifestArtifactPlan({
|
|
17861
|
+
assetBaseStorageUri,
|
|
17862
|
+
currentBundle,
|
|
17863
|
+
targetBundle,
|
|
17864
|
+
targetManifest
|
|
17865
|
+
}),
|
|
17866
|
+
targetManifest
|
|
17867
|
+
};
|
|
17868
|
+
}
|
|
17869
|
+
async function resolveManifestArtifactsV2({ currentBundle, resolveFileUrl, readStorageText, targetBundle }) {
|
|
17870
|
+
const target = await loadTargetPlan({
|
|
17871
|
+
currentBundle,
|
|
17872
|
+
readStorageText,
|
|
17873
|
+
targetBundle
|
|
17874
|
+
});
|
|
17875
|
+
if (!target) return null;
|
|
17876
|
+
const manifestUrl = await resolveFileUrl(target.manifestStorageUri);
|
|
17877
|
+
if (!manifestUrl) return null;
|
|
17878
|
+
const patched = target.plan.assets.find((asset) => asset.patch !== null);
|
|
17879
|
+
let patch;
|
|
17880
|
+
if (patched?.patch && !(patched.file.byteSize !== null && patched.patch.byteSize !== null && patched.patch.byteSize >= patched.file.byteSize)) try {
|
|
17881
|
+
const patchUrl = await resolveFileUrl(patched.patch.storageUri);
|
|
17882
|
+
if (patchUrl) patch = {
|
|
17883
|
+
algorithm: "bsdiff",
|
|
17884
|
+
assetPath: patched.assetPath,
|
|
17885
|
+
baseBundleId: patched.patch.baseBundleId,
|
|
17886
|
+
baseFileHash: patched.patch.baseFileHash,
|
|
17887
|
+
patchFileHash: patched.patch.patchFileHash,
|
|
17888
|
+
patchUrl,
|
|
17889
|
+
...patched.patch.byteSize === null ? {} : { byteSize: patched.patch.byteSize }
|
|
17890
|
+
};
|
|
17891
|
+
} catch {}
|
|
17892
|
+
let archiveUrl = null;
|
|
17893
|
+
const archive = target.targetManifest.archive;
|
|
17894
|
+
if (archive && isContentAddressedAssetFileHash(archive.downloadFileHash) && (asByteSize(archive.downloadByteSize) ?? 0) > 0 && (asByteSize(archive.tarByteSize) ?? 0) > 0) try {
|
|
17895
|
+
archiveUrl = await resolveFileUrl(getBundleArchiveStorageUri({
|
|
17896
|
+
manifestStorageUri: target.manifestStorageUri,
|
|
17897
|
+
bundleId: targetBundle.id
|
|
17898
|
+
}));
|
|
17899
|
+
} catch {}
|
|
17900
|
+
return {
|
|
17901
|
+
artifactProtocolVersion: 2,
|
|
17902
|
+
manifestFileHash: target.manifestFileHash,
|
|
17903
|
+
manifestUrl,
|
|
17904
|
+
...archiveUrl ? { archiveUrl } : {},
|
|
17905
|
+
...patch ? { patch } : {}
|
|
17906
|
+
};
|
|
17907
|
+
}
|
|
17908
|
+
async function resolveManifestArtifactFiles({ paths, resolveFileUrl, readStorageText, targetBundle }) {
|
|
17909
|
+
if (paths.length === 0 || paths.length > 100 || new Set(paths).size !== paths.length) return null;
|
|
17910
|
+
const target = await loadTargetPlan({
|
|
17911
|
+
currentBundle: null,
|
|
17912
|
+
readStorageText,
|
|
17913
|
+
targetBundle
|
|
17914
|
+
});
|
|
17915
|
+
if (!target) return null;
|
|
17916
|
+
const planned = new Map(target.plan.assets.map((asset) => [asset.assetPath, asset]));
|
|
17917
|
+
const requested = paths.map((path) => planned.get(path));
|
|
17918
|
+
if (requested.some((asset) => asset === void 0)) return null;
|
|
17919
|
+
const files = await Promise.all(requested.map(async (asset) => {
|
|
17920
|
+
const url = await resolveFileUrl(asset.file.storageUri);
|
|
17921
|
+
if (!url) return null;
|
|
17922
|
+
const file = { url };
|
|
17923
|
+
if (asset.file.compression) file.compression = asset.file.compression;
|
|
17924
|
+
return [asset.assetPath, file];
|
|
17925
|
+
}));
|
|
17926
|
+
if (files.some((file) => file === null)) return null;
|
|
17927
|
+
return { files: Object.fromEntries(files.filter((file) => file !== null)) };
|
|
17928
|
+
}
|
|
17850
17929
|
//#endregion
|
|
17851
17930
|
//#region ../../node_modules/.pnpm/verkit@0.4.0/node_modules/verkit/dist/comparison-DenM3wCn.js
|
|
17852
17931
|
const LETTER_DASH_NUMBER = "[a-zA-Z0-9-]";
|
|
@@ -18308,20 +18387,33 @@ const createCoreReads = (db, storage) => {
|
|
|
18308
18387
|
const row = await db.findOne("release_catalogs", { scope_key: scopeKey });
|
|
18309
18388
|
return projectReleaseCatalogRow(row === null ? null : toCatalogRow(row), input, scopeKey);
|
|
18310
18389
|
},
|
|
18311
|
-
async
|
|
18390
|
+
getArtifactInfo: (async (targetBundleId, currentBundleId, artifactProtocolVersion) => {
|
|
18312
18391
|
const { readStorageText } = storage;
|
|
18313
|
-
if (artifactProtocolVersion !== 1 || readStorageText === void 0) return null;
|
|
18392
|
+
if (artifactProtocolVersion !== 1 && artifactProtocolVersion !== 2 || readStorageText === void 0) return null;
|
|
18314
18393
|
const withCurrent = currentBundleId !== NIL_UUID;
|
|
18315
18394
|
const [[target, current], patch] = await Promise.all([db.findByKeys("bundles", withCurrent ? [{ id: targetBundleId }, { id: currentBundleId }] : [{ id: targetBundleId }]), withCurrent ? db.findOne("bundle_patches", {
|
|
18316
18395
|
bundle_id: targetBundleId,
|
|
18317
18396
|
base_bundle_id: currentBundleId
|
|
18318
18397
|
}) : null]);
|
|
18319
18398
|
if (target === null || target === void 0) return null;
|
|
18320
|
-
|
|
18399
|
+
const input = {
|
|
18321
18400
|
currentBundle: current ? rowToBundle(toBundleRow(current)) : null,
|
|
18322
18401
|
readStorageText,
|
|
18323
18402
|
resolveFileUrl: storage.resolveFileUrl,
|
|
18324
18403
|
targetBundle: rowToBundle(toBundleRow(target), patch === null ? [] : [toPatchRow(patch)])
|
|
18404
|
+
};
|
|
18405
|
+
return artifactProtocolVersion === 2 ? resolveManifestArtifactsV2(input) : resolveManifestArtifacts(input);
|
|
18406
|
+
}),
|
|
18407
|
+
async getArtifactFiles(bundleId, paths) {
|
|
18408
|
+
const { readStorageText } = storage;
|
|
18409
|
+
if (readStorageText === void 0) return null;
|
|
18410
|
+
const row = await db.findOne("bundles", { id: bundleId });
|
|
18411
|
+
if (row === null) return null;
|
|
18412
|
+
return resolveManifestArtifactFiles({
|
|
18413
|
+
paths,
|
|
18414
|
+
readStorageText,
|
|
18415
|
+
resolveFileUrl: storage.resolveFileUrl,
|
|
18416
|
+
targetBundle: rowToBundle(toBundleRow(row))
|
|
18325
18417
|
});
|
|
18326
18418
|
},
|
|
18327
18419
|
async getBundle(id) {
|
|
@@ -19598,11 +19690,23 @@ const ADMIN_ROUTES = [
|
|
|
19598
19690
|
//#region ../../packages/server/dist/handlerReleaseCatalogRoutes.mjs
|
|
19599
19691
|
const CATALOG_CONTENT_TYPE = "application/vnd.hot-updater.release-catalog+json; version=1";
|
|
19600
19692
|
const ARTIFACT_CONTENT_TYPE = "application/vnd.hot-updater.artifact+json; version=1";
|
|
19693
|
+
const ARTIFACT_V2_CONTENT_TYPE = "application/vnd.hot-updater.artifact+json; version=2";
|
|
19601
19694
|
const ORIGIN_CACHE_TTL_MS = 5e3;
|
|
19602
19695
|
const ORIGIN_CACHE_MAX_ENTRIES = 128;
|
|
19603
19696
|
const NO_CATALOG_HEADER = "x-hot-updater-catalog";
|
|
19604
19697
|
const CATALOG_CACHE_CONTROL = "public, max-age=0, s-maxage=5";
|
|
19605
19698
|
const CATALOG_CDN_CACHE_CONTROL = "public, max-age=5, stale-while-revalidate=5, stale-if-error=0";
|
|
19699
|
+
const readArtifactFilePaths = async (request) => {
|
|
19700
|
+
let body;
|
|
19701
|
+
try {
|
|
19702
|
+
body = await request.json();
|
|
19703
|
+
} catch {
|
|
19704
|
+
return null;
|
|
19705
|
+
}
|
|
19706
|
+
const paths = body?.paths;
|
|
19707
|
+
if (!Array.isArray(paths) || paths.length === 0 || paths.length > 100 || !paths.every((path) => typeof path === "string" && path.length > 0) || new Set(paths).size !== paths.length) return null;
|
|
19708
|
+
return paths;
|
|
19709
|
+
};
|
|
19606
19710
|
const privateNotFound = () => Response.json({ error: "Not found" }, {
|
|
19607
19711
|
status: 404,
|
|
19608
19712
|
headers: { "cache-control": "private, no-store" }
|
|
@@ -19712,6 +19816,30 @@ const createReleaseCatalogRouteHandlers = () => {
|
|
|
19712
19816
|
if (invalid) return invalid;
|
|
19713
19817
|
return catalogResponse(await loadCatalog(`fingerprint:${JSON.stringify(input)}`, () => core.getReleaseCatalog(input)), request);
|
|
19714
19818
|
},
|
|
19819
|
+
artifactV2: async (params, _request, { core }) => {
|
|
19820
|
+
const info = await core.getArtifactInfo(requireRouteParam(params, "targetBundleId"), requireRouteParam(params, "currentBundleId"), 2);
|
|
19821
|
+
if (info === null) return privateNotFound();
|
|
19822
|
+
return new Response(JSON.stringify(info), {
|
|
19823
|
+
status: 200,
|
|
19824
|
+
headers: {
|
|
19825
|
+
"cache-control": "private, no-store",
|
|
19826
|
+
"content-type": ARTIFACT_V2_CONTENT_TYPE
|
|
19827
|
+
}
|
|
19828
|
+
});
|
|
19829
|
+
},
|
|
19830
|
+
artifactFilesV2: async (params, request, { core }) => {
|
|
19831
|
+
const paths = await readArtifactFilePaths(request);
|
|
19832
|
+
if (paths === null) return badRequest(`paths must be 1 to 100 unique strings`);
|
|
19833
|
+
const files = await core.getArtifactFiles(requireRouteParam(params, "targetBundleId"), paths);
|
|
19834
|
+
if (files === null) return privateNotFound();
|
|
19835
|
+
return new Response(JSON.stringify(files), {
|
|
19836
|
+
status: 200,
|
|
19837
|
+
headers: {
|
|
19838
|
+
"cache-control": "private, no-store",
|
|
19839
|
+
"content-type": ARTIFACT_V2_CONTENT_TYPE
|
|
19840
|
+
}
|
|
19841
|
+
});
|
|
19842
|
+
},
|
|
19715
19843
|
artifactV1: async (params, _request, { core }) => {
|
|
19716
19844
|
const info = await core.getArtifactInfo(requireRouteParam(params, "targetBundleId"), requireRouteParam(params, "currentBundleId"), 1);
|
|
19717
19845
|
if (info === null) return privateNotFound();
|
|
@@ -19862,6 +19990,8 @@ function createHotUpdaterHandlers({ api, clientPolicy, endpoints = [], plugins =
|
|
|
19862
19990
|
addClientRoute("GET", "/release-catalogs/app-version/:platform/:channelKey/:appVersion", "appVersionReleaseCatalog");
|
|
19863
19991
|
addClientRoute("GET", "/release-catalogs/fingerprint/:platform/:channelKey/:fingerprintHash", "fingerprintReleaseCatalog");
|
|
19864
19992
|
addClientRoute("GET", "/artifacts/v1/:targetBundleId/from/:currentBundleId", "artifactV1");
|
|
19993
|
+
addClientRoute("GET", "/artifacts/v2/:targetBundleId/from/:currentBundleId", "artifactV2");
|
|
19994
|
+
addClientRoute("POST", "/artifacts/v2/:targetBundleId/files", "artifactFilesV2");
|
|
19865
19995
|
const adminRouter = createRouter();
|
|
19866
19996
|
const addAdminRoute = mount(adminRouter, true);
|
|
19867
19997
|
addAdminRoute("GET", "/version", "adminVersion");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/vercel",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.7",
|
|
5
5
|
"description": "React Native OTA solution for self-hosted",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.mjs",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"@vercel/cli-auth": "0.3.10",
|
|
42
42
|
"@vercel/cli-config": "0.3.1",
|
|
43
43
|
"pg": "8.13.1",
|
|
44
|
-
"@hot-updater/cli-tools": "1.0.
|
|
45
|
-
"@hot-updater/postgres": "1.0.
|
|
46
|
-
"@hot-updater/
|
|
47
|
-
"@hot-updater/plugin-core": "1.0.
|
|
48
|
-
"@hot-updater/
|
|
44
|
+
"@hot-updater/cli-tools": "1.0.7",
|
|
45
|
+
"@hot-updater/postgres": "1.0.7",
|
|
46
|
+
"@hot-updater/server": "1.0.7",
|
|
47
|
+
"@hot-updater/plugin-core": "1.0.7",
|
|
48
|
+
"@hot-updater/protocol": "1.0.7"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^20",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"execa": "9.5.2",
|
|
55
55
|
"kysely": "0.28.17",
|
|
56
56
|
"vitest": "4.1.4",
|
|
57
|
-
"@hot-updater/test-utils": "1.0.
|
|
57
|
+
"@hot-updater/test-utils": "1.0.7"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
60
60
|
"build": "tsdown",
|