@hot-updater/server 0.31.4 → 0.33.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/_virtual/_rolldown/runtime.cjs +1 -1
- package/dist/_virtual/_rolldown/runtime.mjs +1 -1
- package/dist/db/createBundleDiff.cjs +19 -13
- package/dist/db/createBundleDiff.mjs +15 -9
- package/dist/db/index.cjs +7 -10
- package/dist/db/index.mjs +7 -10
- package/dist/db/pluginCore.cjs +136 -96
- package/dist/db/pluginCore.mjs +137 -97
- package/dist/db/requestBundleIdentityMap.cjs +29 -0
- package/dist/db/requestBundleIdentityMap.mjs +29 -0
- package/dist/db/schemaEnhancements.cjs +1 -1
- package/dist/db/types.d.cts +2 -1
- package/dist/db/types.d.mts +2 -1
- package/dist/db/updateArtifacts.cjs +6 -6
- package/dist/db/updateArtifacts.mjs +6 -6
- package/dist/handler.cjs +18 -8
- package/dist/handler.d.cts +9 -10
- package/dist/handler.d.mts +9 -10
- package/dist/handler.mjs +17 -7
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/index.d.cts +1 -1
- package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/index.d.mts +1 -1
- package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/query/index.d.cts +1 -1
- package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/query/index.d.mts +1 -1
- package/dist/packages/server/package.cjs +1 -1
- package/dist/packages/server/package.mjs +1 -1
- package/dist/runtime.cjs +10 -12
- package/dist/runtime.mjs +10 -12
- package/package.json +7 -7
- package/src/db/createBundleDiff.spec.ts +3 -0
- package/src/db/createBundleDiff.ts +27 -21
- package/src/db/index.spec.ts +36 -0
- package/src/db/index.ts +6 -10
- package/src/db/pluginCore.spec.ts +443 -0
- package/src/db/pluginCore.ts +63 -7
- package/src/db/requestBundleIdentityMap.spec.ts +56 -0
- package/src/db/requestBundleIdentityMap.ts +61 -0
- package/src/db/types.ts +2 -0
- package/src/db/updateArtifacts.ts +8 -19
- package/src/handler-standalone.integration.spec.ts +12 -0
- package/src/handler.spec.ts +117 -19
- package/src/handler.ts +47 -21
- package/src/runtime.spec.ts +46 -4
- package/src/runtime.ts +10 -12
|
@@ -46,4 +46,4 @@ interface FumaDBFactory<Schemas extends AnySchema[]> {
|
|
|
46
46
|
}
|
|
47
47
|
type InferFumaDB<Factory extends FumaDBFactory<any>> = Factory extends FumaDBFactory<infer Schemas> ? FumaDB<Schemas> : never;
|
|
48
48
|
//#endregion
|
|
49
|
-
export type
|
|
49
|
+
export { type FumaDBFactory, type InferFumaDB };
|
package/dist/runtime.cjs
CHANGED
|
@@ -22,23 +22,21 @@ function createHotUpdater(options) {
|
|
|
22
22
|
createMutationPlugin: () => database(),
|
|
23
23
|
readStorageText
|
|
24
24
|
} : { readStorageText });
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
routes: options.routes
|
|
30
|
-
}),
|
|
31
|
-
adapterName: core.adapterName
|
|
32
|
-
};
|
|
25
|
+
const internalHandler = require_handler.createHandler(core.api, {
|
|
26
|
+
basePath,
|
|
27
|
+
routes: options.routes
|
|
28
|
+
});
|
|
33
29
|
const handler = (request, context, ...extraArgs) => {
|
|
34
|
-
if (extraArgs.length > 0) return
|
|
35
|
-
return
|
|
30
|
+
if (extraArgs.length > 0) return internalHandler(request);
|
|
31
|
+
return internalHandler(request, context);
|
|
36
32
|
};
|
|
37
|
-
|
|
38
|
-
...api,
|
|
33
|
+
const api = {
|
|
39
34
|
basePath,
|
|
35
|
+
adapterName: core.adapterName,
|
|
40
36
|
handler
|
|
41
37
|
};
|
|
38
|
+
Object.defineProperties(api, Object.getOwnPropertyDescriptors(core.api));
|
|
39
|
+
return api;
|
|
42
40
|
}
|
|
43
41
|
//#endregion
|
|
44
42
|
exports.HOT_UPDATER_SERVER_VERSION = require_version.HOT_UPDATER_SERVER_VERSION;
|
package/dist/runtime.mjs
CHANGED
|
@@ -20,23 +20,21 @@ function createHotUpdater(options) {
|
|
|
20
20
|
createMutationPlugin: () => database(),
|
|
21
21
|
readStorageText
|
|
22
22
|
} : { readStorageText });
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
routes: options.routes
|
|
28
|
-
}),
|
|
29
|
-
adapterName: core.adapterName
|
|
30
|
-
};
|
|
23
|
+
const internalHandler = createHandler(core.api, {
|
|
24
|
+
basePath,
|
|
25
|
+
routes: options.routes
|
|
26
|
+
});
|
|
31
27
|
const handler = (request, context, ...extraArgs) => {
|
|
32
|
-
if (extraArgs.length > 0) return
|
|
33
|
-
return
|
|
28
|
+
if (extraArgs.length > 0) return internalHandler(request);
|
|
29
|
+
return internalHandler(request, context);
|
|
34
30
|
};
|
|
35
|
-
|
|
36
|
-
...api,
|
|
31
|
+
const api = {
|
|
37
32
|
basePath,
|
|
33
|
+
adapterName: core.adapterName,
|
|
38
34
|
handler
|
|
39
35
|
};
|
|
36
|
+
Object.defineProperties(api, Object.getOwnPropertyDescriptors(core.api));
|
|
37
|
+
return api;
|
|
40
38
|
}
|
|
41
39
|
//#endregion
|
|
42
40
|
export { HOT_UPDATER_SERVER_VERSION, createHandler, createHotUpdater };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.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
|
"mongodb": "6.20.0",
|
|
56
56
|
"rou3": "0.7.9",
|
|
57
57
|
"semver": "^7.7.2",
|
|
58
|
-
"@hot-updater/
|
|
59
|
-
"@hot-updater/
|
|
60
|
-
"@hot-updater/
|
|
61
|
-
"@hot-updater/
|
|
58
|
+
"@hot-updater/core": "0.33.0",
|
|
59
|
+
"@hot-updater/bsdiff": "0.33.0",
|
|
60
|
+
"@hot-updater/plugin-core": "0.33.0",
|
|
61
|
+
"@hot-updater/js": "0.33.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@electric-sql/pglite": "0.2.17",
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
"kysely-pglite-dialect": "1.2.0",
|
|
69
69
|
"msw": "^2.7.0",
|
|
70
70
|
"uuidv7": "^1.0.2",
|
|
71
|
-
"@hot-updater/standalone": "0.
|
|
72
|
-
"@hot-updater/test-utils": "0.
|
|
71
|
+
"@hot-updater/standalone": "0.33.0",
|
|
72
|
+
"@hot-updater/test-utils": "0.33.0"
|
|
73
73
|
},
|
|
74
74
|
"inlinedDependencies": {
|
|
75
75
|
"@noble/hashes": "1.8.0",
|
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
DatabasePlugin,
|
|
18
18
|
NodeStoragePlugin,
|
|
19
19
|
} from "@hot-updater/plugin-core";
|
|
20
|
+
import { resolveManifestAssetStorageUri } from "@hot-updater/plugin-core";
|
|
20
21
|
|
|
21
22
|
type BundleManifest = {
|
|
22
23
|
bundleId: string;
|
|
@@ -80,21 +81,6 @@ const isBundleManifest = (value: unknown): value is BundleManifest => {
|
|
|
80
81
|
);
|
|
81
82
|
};
|
|
82
83
|
|
|
83
|
-
const createChildStorageUri = (
|
|
84
|
-
baseStorageUri: string,
|
|
85
|
-
relativePath: string,
|
|
86
|
-
) => {
|
|
87
|
-
const baseUrl = new URL(baseStorageUri);
|
|
88
|
-
const normalizedBasePath = baseUrl.pathname.replace(/\/+$/, "");
|
|
89
|
-
const relativeSegments = relativePath
|
|
90
|
-
.split("/")
|
|
91
|
-
.filter(Boolean)
|
|
92
|
-
.map((segment) => encodeURIComponent(segment));
|
|
93
|
-
|
|
94
|
-
baseUrl.pathname = `${normalizedBasePath}/${relativeSegments.join("/")}`;
|
|
95
|
-
return baseUrl.toString();
|
|
96
|
-
};
|
|
97
|
-
|
|
98
84
|
const getRelativeStorageDir = (relativePath: string) => {
|
|
99
85
|
const normalized = relativePath.replace(/\\/g, "/");
|
|
100
86
|
const dirname = path.posix.dirname(normalized);
|
|
@@ -188,18 +174,24 @@ function resolveHbcAssetPath(manifest: BundleManifest) {
|
|
|
188
174
|
async function fetchAssetBytes(
|
|
189
175
|
bundle: Bundle,
|
|
190
176
|
assetPath: string,
|
|
177
|
+
manifest: BundleManifest,
|
|
191
178
|
storagePlugin: NodeStoragePlugin | null,
|
|
192
179
|
) {
|
|
193
180
|
const assetBaseStorageUri = getAssetBaseStorageUri(bundle);
|
|
194
181
|
if (!assetBaseStorageUri) {
|
|
195
182
|
throw new Error(`Bundle ${bundle.id} does not have asset storage metadata`);
|
|
196
183
|
}
|
|
184
|
+
const asset = manifest.assets[assetPath];
|
|
185
|
+
if (!asset) {
|
|
186
|
+
throw new Error(`Asset ${assetPath} is missing from manifest`);
|
|
187
|
+
}
|
|
197
188
|
|
|
198
189
|
if (BR_COMPRESSED_ASSET_PATH_RE.test(assetPath)) {
|
|
199
|
-
const compressedAssetStorageUri =
|
|
190
|
+
const compressedAssetStorageUri = resolveManifestAssetStorageUri({
|
|
200
191
|
assetBaseStorageUri,
|
|
201
|
-
`${assetPath}.br`,
|
|
202
|
-
|
|
192
|
+
assetPath: `${assetPath}.br`,
|
|
193
|
+
fileHash: asset.fileHash,
|
|
194
|
+
});
|
|
203
195
|
|
|
204
196
|
let compressedBytes: Uint8Array | null = null;
|
|
205
197
|
try {
|
|
@@ -216,7 +208,11 @@ async function fetchAssetBytes(
|
|
|
216
208
|
}
|
|
217
209
|
}
|
|
218
210
|
|
|
219
|
-
const assetStorageUri =
|
|
211
|
+
const assetStorageUri = resolveManifestAssetStorageUri({
|
|
212
|
+
assetBaseStorageUri,
|
|
213
|
+
assetPath,
|
|
214
|
+
fileHash: asset.fileHash,
|
|
215
|
+
});
|
|
220
216
|
return downloadStorageBytes(assetStorageUri, storagePlugin);
|
|
221
217
|
}
|
|
222
218
|
|
|
@@ -300,8 +296,18 @@ export async function createBundleDiff(
|
|
|
300
296
|
}
|
|
301
297
|
|
|
302
298
|
const [baseBytes, targetBytes] = await Promise.all([
|
|
303
|
-
fetchAssetBytes(
|
|
304
|
-
|
|
299
|
+
fetchAssetBytes(
|
|
300
|
+
baseBundle,
|
|
301
|
+
baseAssetPath,
|
|
302
|
+
baseManifest,
|
|
303
|
+
deps.storagePlugin,
|
|
304
|
+
),
|
|
305
|
+
fetchAssetBytes(
|
|
306
|
+
targetBundle,
|
|
307
|
+
targetAssetPath,
|
|
308
|
+
targetManifest,
|
|
309
|
+
deps.storagePlugin,
|
|
310
|
+
),
|
|
305
311
|
]);
|
|
306
312
|
|
|
307
313
|
const patchBytes = await hdiff(baseBytes, targetBytes);
|
package/src/db/index.spec.ts
CHANGED
|
@@ -866,6 +866,42 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
866
866
|
});
|
|
867
867
|
|
|
868
868
|
describe("database plugin factories", () => {
|
|
869
|
+
it("keeps optional maintenance capabilities lazy", () => {
|
|
870
|
+
const factory = vi.fn(() => ({
|
|
871
|
+
async getBundleById() {
|
|
872
|
+
return null;
|
|
873
|
+
},
|
|
874
|
+
async getBundles() {
|
|
875
|
+
return {
|
|
876
|
+
data: [],
|
|
877
|
+
pagination: {
|
|
878
|
+
hasNextPage: false,
|
|
879
|
+
hasPreviousPage: false,
|
|
880
|
+
currentPage: 1,
|
|
881
|
+
totalPages: 1,
|
|
882
|
+
total: 0,
|
|
883
|
+
},
|
|
884
|
+
};
|
|
885
|
+
},
|
|
886
|
+
async getChannels() {
|
|
887
|
+
return [];
|
|
888
|
+
},
|
|
889
|
+
async commitBundle() {},
|
|
890
|
+
}));
|
|
891
|
+
const hotUpdater = createHotUpdater({
|
|
892
|
+
database: createDatabasePlugin({
|
|
893
|
+
name: "lazyPlugin",
|
|
894
|
+
factory,
|
|
895
|
+
})({}),
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
expect(factory).not.toHaveBeenCalled();
|
|
899
|
+
expect(hotUpdater.diagnostics).toBeUndefined();
|
|
900
|
+
expect(factory).not.toHaveBeenCalled();
|
|
901
|
+
expect(hotUpdater.diagnostics).toBeUndefined();
|
|
902
|
+
expect(factory).not.toHaveBeenCalled();
|
|
903
|
+
});
|
|
904
|
+
|
|
869
905
|
it("isolates pending mutation state between overlapping writes", async () => {
|
|
870
906
|
const committedBundleIds: string[][] = [];
|
|
871
907
|
const onUnmount = vi.fn(async () => undefined);
|
package/src/db/index.ts
CHANGED
|
@@ -104,19 +104,15 @@ export function createHotUpdater<TContext = unknown>(
|
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
const api = {
|
|
107
|
-
|
|
107
|
+
basePath,
|
|
108
|
+
adapterName: core.adapterName,
|
|
109
|
+
createMigrator: core.createMigrator,
|
|
110
|
+
generateSchema: core.generateSchema,
|
|
108
111
|
handler: createHandler(core.api, {
|
|
109
112
|
basePath,
|
|
110
113
|
routes: options.routes,
|
|
111
114
|
}),
|
|
112
|
-
adapterName: core.adapterName,
|
|
113
|
-
createMigrator: core.createMigrator,
|
|
114
|
-
generateSchema: core.generateSchema,
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
return {
|
|
118
|
-
...api,
|
|
119
|
-
basePath,
|
|
120
|
-
handler: api.handler,
|
|
121
115
|
};
|
|
116
|
+
Object.defineProperties(api, Object.getOwnPropertyDescriptors(core.api));
|
|
117
|
+
return api as HotUpdaterAPI<TContext>;
|
|
122
118
|
}
|