@hot-updater/server 0.28.0 → 0.29.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/drizzle.cjs +7 -7
- package/dist/adapters/drizzle.mjs +2 -0
- package/dist/adapters/kysely.cjs +7 -7
- package/dist/adapters/kysely.mjs +2 -0
- package/dist/adapters/mongodb.cjs +7 -7
- package/dist/adapters/mongodb.mjs +2 -0
- package/dist/adapters/prisma.cjs +7 -7
- package/dist/adapters/prisma.mjs +2 -0
- package/dist/calculatePagination.cjs +1 -3
- package/dist/{calculatePagination.js → calculatePagination.mjs} +1 -2
- package/dist/db/index.cjs +24 -15
- package/dist/db/index.d.cts +12 -9
- package/dist/db/index.d.mts +30 -0
- package/dist/db/index.mjs +45 -0
- package/dist/db/ormCore.cjs +247 -138
- package/dist/db/ormCore.d.cts +35 -17
- package/dist/db/ormCore.d.mts +44 -0
- package/dist/db/ormCore.mjs +386 -0
- package/dist/db/pluginCore.cjs +145 -40
- package/dist/db/pluginCore.mjs +176 -0
- package/dist/db/types.cjs +1 -3
- package/dist/db/types.d.cts +14 -21
- package/dist/db/types.d.mts +24 -0
- package/dist/db/{types.js → types.mjs} +1 -2
- package/dist/handler.cjs +117 -48
- package/dist/handler.d.cts +28 -18
- package/dist/handler.d.mts +47 -0
- package/dist/handler.mjs +217 -0
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +3 -3
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +4 -0
- package/dist/internalRouter.cjs +54 -0
- package/dist/internalRouter.mjs +52 -0
- package/dist/node.cjs +2 -3
- package/dist/node.d.cts +0 -1
- package/dist/{node.d.ts → node.d.mts} +1 -2
- package/dist/{node.js → node.mjs} +1 -2
- package/dist/route.cjs +7 -0
- package/dist/route.mjs +7 -0
- package/dist/runtime.cjs +42 -0
- package/dist/runtime.d.cts +21 -0
- package/dist/runtime.d.mts +21 -0
- package/dist/runtime.mjs +40 -0
- package/dist/schema/v0_21_0.cjs +1 -5
- package/dist/schema/{v0_21_0.js → v0_21_0.mjs} +1 -3
- package/dist/schema/v0_29_0.cjs +24 -0
- package/dist/schema/v0_29_0.mjs +24 -0
- package/dist/types/{index.d.ts → index.d.mts} +1 -1
- package/package.json +18 -18
- package/src/db/index.spec.ts +64 -29
- package/src/db/index.ts +55 -35
- package/src/db/ormCore.ts +438 -210
- package/src/db/ormUpdateCheck.bench.ts +261 -0
- package/src/db/pluginCore.ts +298 -49
- package/src/db/pluginUpdateCheck.bench.ts +250 -0
- package/src/db/types.ts +52 -27
- package/src/{handler-standalone-integration.spec.ts → handler-standalone.integration.spec.ts} +106 -0
- package/src/handler.spec.ts +156 -0
- package/src/handler.ts +296 -77
- package/src/internalRouter.ts +104 -0
- package/src/route.ts +7 -0
- package/src/runtime.spec.ts +277 -0
- package/src/runtime.ts +121 -0
- package/src/schema/v0_29_0.ts +26 -0
- package/dist/_virtual/rolldown_runtime.cjs +0 -25
- package/dist/adapters/drizzle.js +0 -3
- package/dist/adapters/kysely.js +0 -3
- package/dist/adapters/mongodb.js +0 -3
- package/dist/adapters/prisma.js +0 -3
- package/dist/db/index.d.ts +0 -27
- package/dist/db/index.js +0 -36
- package/dist/db/ormCore.d.ts +0 -26
- package/dist/db/ormCore.js +0 -273
- package/dist/db/pluginCore.js +0 -69
- package/dist/db/types.d.ts +0 -31
- package/dist/handler.d.ts +0 -37
- package/dist/handler.js +0 -146
- package/dist/index.d.ts +0 -5
- package/dist/index.js +0 -5
- /package/dist/adapters/{drizzle.d.ts → drizzle.d.mts} +0 -0
- /package/dist/adapters/{kysely.d.ts → kysely.d.mts} +0 -0
- /package/dist/adapters/{mongodb.d.ts → mongodb.d.mts} +0 -0
- /package/dist/adapters/{prisma.d.ts → prisma.d.mts} +0 -0
package/package.json
CHANGED
|
@@ -1,37 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "React Native OTA solution for self-hosted",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "./dist/index.cjs",
|
|
8
|
-
"module": "./dist/index.
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
9
|
"types": "./dist/index.d.cts",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
|
-
"import": "./dist/index.
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
13
|
"require": "./dist/index.cjs"
|
|
14
14
|
},
|
|
15
15
|
"./adapters/drizzle": {
|
|
16
|
-
"import": "./dist/adapters/drizzle.
|
|
16
|
+
"import": "./dist/adapters/drizzle.mjs",
|
|
17
17
|
"require": "./dist/adapters/drizzle.cjs"
|
|
18
18
|
},
|
|
19
19
|
"./adapters/kysely": {
|
|
20
|
-
"import": "./dist/adapters/kysely.
|
|
20
|
+
"import": "./dist/adapters/kysely.mjs",
|
|
21
21
|
"require": "./dist/adapters/kysely.cjs"
|
|
22
22
|
},
|
|
23
23
|
"./adapters/mongodb": {
|
|
24
|
-
"import": "./dist/adapters/mongodb.
|
|
24
|
+
"import": "./dist/adapters/mongodb.mjs",
|
|
25
25
|
"require": "./dist/adapters/mongodb.cjs"
|
|
26
26
|
},
|
|
27
27
|
"./adapters/prisma": {
|
|
28
|
-
"import": "./dist/adapters/prisma.
|
|
28
|
+
"import": "./dist/adapters/prisma.mjs",
|
|
29
29
|
"require": "./dist/adapters/prisma.cjs"
|
|
30
30
|
},
|
|
31
31
|
"./node": {
|
|
32
|
-
"import": "./dist/node.
|
|
32
|
+
"import": "./dist/node.mjs",
|
|
33
33
|
"require": "./dist/node.cjs"
|
|
34
34
|
},
|
|
35
|
+
"./runtime": {
|
|
36
|
+
"import": "./dist/runtime.mjs",
|
|
37
|
+
"require": "./dist/runtime.cjs"
|
|
38
|
+
},
|
|
35
39
|
"./package.json": "./package.json"
|
|
36
40
|
},
|
|
37
41
|
"files": [
|
|
@@ -49,25 +53,21 @@
|
|
|
49
53
|
"fumadb": "0.2.2",
|
|
50
54
|
"rou3": "0.7.9",
|
|
51
55
|
"semver": "^7.7.2",
|
|
52
|
-
"@hot-updater/core": "0.
|
|
53
|
-
"@hot-updater/plugin-core": "0.
|
|
54
|
-
"@hot-updater/js": "0.
|
|
56
|
+
"@hot-updater/core": "0.29.0",
|
|
57
|
+
"@hot-updater/plugin-core": "0.29.0",
|
|
58
|
+
"@hot-updater/js": "0.29.0"
|
|
55
59
|
},
|
|
56
60
|
"devDependencies": {
|
|
57
61
|
"@electric-sql/pglite": "^0.2.17",
|
|
58
62
|
"@types/node": "^20",
|
|
59
63
|
"@types/semver": "^7.5.8",
|
|
60
|
-
"execa": "
|
|
64
|
+
"execa": "9.5.2",
|
|
61
65
|
"kysely": "^0.28.9",
|
|
62
66
|
"kysely-pglite-dialect": "^1.2.0",
|
|
63
67
|
"msw": "^2.7.0",
|
|
64
68
|
"uuidv7": "^1.0.2",
|
|
65
|
-
"@hot-updater/
|
|
66
|
-
"@hot-updater/
|
|
67
|
-
"@hot-updater/standalone": "0.28.0",
|
|
68
|
-
"@hot-updater/supabase": "0.28.0",
|
|
69
|
-
"@hot-updater/test-utils": "0.28.0",
|
|
70
|
-
"@hot-updater/firebase": "0.28.0"
|
|
69
|
+
"@hot-updater/test-utils": "0.29.0",
|
|
70
|
+
"@hot-updater/standalone": "0.29.0"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
73
|
"build": "tsdown",
|
package/src/db/index.spec.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { PGlite } from "@electric-sql/pglite";
|
|
2
|
-
import { s3Storage } from "@hot-updater/aws";
|
|
3
|
-
import { r2Storage } from "@hot-updater/cloudflare";
|
|
4
2
|
import type { Bundle, GetBundlesArgs, UpdateInfo } from "@hot-updater/core";
|
|
5
3
|
import { NIL_UUID } from "@hot-updater/core";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import type {
|
|
5
|
+
StoragePlugin,
|
|
6
|
+
StorageResolveContext,
|
|
7
|
+
} from "@hot-updater/plugin-core";
|
|
8
|
+
import {
|
|
9
|
+
setupBundleMethodsTestSuite,
|
|
10
|
+
setupGetUpdateInfoTestSuite,
|
|
11
|
+
} from "@hot-updater/test-utils";
|
|
9
12
|
import { Kysely } from "kysely";
|
|
10
13
|
import { PGliteDialect } from "kysely-pglite-dialect";
|
|
11
14
|
import {
|
|
@@ -21,6 +24,28 @@ import {
|
|
|
21
24
|
import { kyselyAdapter } from "../adapters/kysely";
|
|
22
25
|
import { createHotUpdater } from "./index";
|
|
23
26
|
|
|
27
|
+
function createTestStoragePlugin(
|
|
28
|
+
protocol: string,
|
|
29
|
+
resolveFileUrl: (
|
|
30
|
+
storageUri: string,
|
|
31
|
+
context?: StorageResolveContext,
|
|
32
|
+
) => string,
|
|
33
|
+
): StoragePlugin {
|
|
34
|
+
return {
|
|
35
|
+
name: `${protocol}TestStorage`,
|
|
36
|
+
supportedProtocol: protocol,
|
|
37
|
+
async upload(key) {
|
|
38
|
+
return {
|
|
39
|
+
storageUri: `${protocol}://test-bucket/${key}`,
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
async delete() {},
|
|
43
|
+
async getDownloadUrl(storageUri, context) {
|
|
44
|
+
return { fileUrl: resolveFileUrl(storageUri, context) };
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
24
49
|
describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
25
50
|
const db = new PGlite();
|
|
26
51
|
|
|
@@ -32,27 +57,29 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
32
57
|
provider: "postgresql",
|
|
33
58
|
}),
|
|
34
59
|
storages: [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
createTestStoragePlugin("s3", (storageUri) =>
|
|
61
|
+
storageUri
|
|
62
|
+
.replace("s3://", "https://s3.example.com/")
|
|
63
|
+
.replace(/([^:]\/)\/+/g, "$1"),
|
|
64
|
+
),
|
|
65
|
+
createTestStoragePlugin("r2", (storageUri) =>
|
|
66
|
+
storageUri
|
|
67
|
+
.replace("r2://", "https://r2.example.com/")
|
|
68
|
+
.replace(/([^:]\/)\/+/g, "$1"),
|
|
69
|
+
),
|
|
70
|
+
createTestStoragePlugin("supabase-storage", (storageUri) =>
|
|
71
|
+
storageUri
|
|
72
|
+
.replace(
|
|
73
|
+
"supabase-storage://",
|
|
74
|
+
"https://supabase.example.com/storage/v1/object/sign/",
|
|
75
|
+
)
|
|
76
|
+
.replace(/([^:]\/)\/+/g, "$1"),
|
|
77
|
+
),
|
|
78
|
+
createTestStoragePlugin("gs", (storageUri) =>
|
|
79
|
+
storageUri
|
|
80
|
+
.replace("gs://", "https://firebase.example.com/")
|
|
81
|
+
.replace(/([^:]\/)\/+/g, "$1"),
|
|
82
|
+
),
|
|
56
83
|
],
|
|
57
84
|
});
|
|
58
85
|
|
|
@@ -87,6 +114,14 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
87
114
|
};
|
|
88
115
|
|
|
89
116
|
setupGetUpdateInfoTestSuite({ getUpdateInfo });
|
|
117
|
+
setupBundleMethodsTestSuite({
|
|
118
|
+
getBundleById: hotUpdater.getBundleById.bind(hotUpdater),
|
|
119
|
+
getChannels: hotUpdater.getChannels.bind(hotUpdater),
|
|
120
|
+
insertBundle: hotUpdater.insertBundle.bind(hotUpdater),
|
|
121
|
+
getBundles: hotUpdater.getBundles.bind(hotUpdater),
|
|
122
|
+
updateBundleById: hotUpdater.updateBundleById.bind(hotUpdater),
|
|
123
|
+
deleteBundleById: hotUpdater.deleteBundleById.bind(hotUpdater),
|
|
124
|
+
});
|
|
90
125
|
|
|
91
126
|
describe("getBundleById", () => {
|
|
92
127
|
it("should retrieve bundle by id without Prisma validation errors", async () => {
|
|
@@ -223,7 +258,7 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
223
258
|
|
|
224
259
|
expect(updateInfo).not.toBeNull();
|
|
225
260
|
expect(updateInfo?.fileUrl).toBe(
|
|
226
|
-
"https://
|
|
261
|
+
"https://s3.example.com/test-bucket/bundles/bundle.zip",
|
|
227
262
|
);
|
|
228
263
|
});
|
|
229
264
|
|
|
@@ -253,7 +288,7 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
253
288
|
|
|
254
289
|
expect(updateInfo).not.toBeNull();
|
|
255
290
|
expect(updateInfo?.fileUrl).toBe(
|
|
256
|
-
"https://
|
|
291
|
+
"https://s3.example.com/bundle/bundle.zip",
|
|
257
292
|
);
|
|
258
293
|
});
|
|
259
294
|
|
|
@@ -322,7 +357,7 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
322
357
|
|
|
323
358
|
expect(updateInfo).not.toBeNull();
|
|
324
359
|
expect(updateInfo?.fileUrl).toBe(
|
|
325
|
-
"https://
|
|
360
|
+
"https://s3.example.com/test-bucket/fp-bundle.zip",
|
|
326
361
|
);
|
|
327
362
|
});
|
|
328
363
|
});
|
package/src/db/index.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
HotUpdaterContext,
|
|
3
|
+
StoragePlugin,
|
|
4
|
+
} from "@hot-updater/plugin-core";
|
|
5
|
+
import { createHandler, type HandlerRoutes } from "../handler";
|
|
6
|
+
import { normalizeBasePath } from "../route";
|
|
3
7
|
import {
|
|
4
8
|
createOrmDatabaseCore,
|
|
5
9
|
type HotUpdaterClient,
|
|
@@ -17,41 +21,45 @@ import {
|
|
|
17
21
|
export type { HotUpdaterClient, Migrator } from "./ormCore";
|
|
18
22
|
export { HotUpdaterDB } from "./ormCore";
|
|
19
23
|
|
|
20
|
-
type
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
export type HotUpdaterAPI<TContext = unknown> = DatabaseAPI<TContext> & {
|
|
25
|
+
basePath: string;
|
|
26
|
+
handler: (
|
|
27
|
+
request: Request,
|
|
28
|
+
context?: HotUpdaterContext<TContext>,
|
|
29
|
+
) => Promise<Response>;
|
|
26
30
|
adapterName: string;
|
|
27
31
|
createMigrator: () => Migrator;
|
|
28
32
|
generateSchema: HotUpdaterClient["generateSchema"];
|
|
29
33
|
};
|
|
30
34
|
|
|
31
|
-
interface
|
|
32
|
-
database: DatabaseAdapter
|
|
35
|
+
export interface CreateHotUpdaterOptions<TContext = unknown> {
|
|
36
|
+
database: DatabaseAdapter<TContext>;
|
|
33
37
|
/**
|
|
34
38
|
* Storage plugins for handling file uploads and downloads.
|
|
35
39
|
*/
|
|
36
|
-
storages?: (StoragePlugin | StoragePluginFactory)[];
|
|
40
|
+
storages?: (StoragePlugin<TContext> | StoragePluginFactory<TContext>)[];
|
|
37
41
|
/**
|
|
38
42
|
* @deprecated Use `storages` instead. This field will be removed in a future version.
|
|
39
43
|
*/
|
|
40
|
-
storagePlugins?: (StoragePlugin | StoragePluginFactory)[];
|
|
44
|
+
storagePlugins?: (StoragePlugin<TContext> | StoragePluginFactory<TContext>)[];
|
|
41
45
|
basePath?: string;
|
|
42
46
|
cwd?: string;
|
|
47
|
+
routes?: HandlerRoutes;
|
|
43
48
|
}
|
|
44
49
|
|
|
45
|
-
export function createHotUpdater
|
|
50
|
+
export function createHotUpdater<TContext = unknown>(
|
|
51
|
+
options: CreateHotUpdaterOptions<TContext>,
|
|
52
|
+
): HotUpdaterAPI<TContext> {
|
|
53
|
+
const basePath = normalizeBasePath(options.basePath ?? "/api");
|
|
54
|
+
|
|
46
55
|
// Initialize storage plugins - call factories if they are functions
|
|
47
|
-
const storagePlugins = (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
[]
|
|
51
|
-
).map((plugin) => (typeof plugin === "function" ? plugin() : plugin));
|
|
56
|
+
const storagePlugins = (options.storages ?? options.storagePlugins ?? []).map(
|
|
57
|
+
(plugin) => (typeof plugin === "function" ? plugin() : plugin),
|
|
58
|
+
);
|
|
52
59
|
|
|
53
|
-
const
|
|
60
|
+
const resolveStoragePluginUrl = async (
|
|
54
61
|
storageUri: string | null,
|
|
62
|
+
context?: HotUpdaterContext<TContext>,
|
|
55
63
|
): Promise<string | null> => {
|
|
56
64
|
if (!storageUri) {
|
|
57
65
|
return null;
|
|
@@ -66,35 +74,47 @@ export function createHotUpdater(options: HotUpdaterOptions): HotUpdaterAPI {
|
|
|
66
74
|
if (!plugin) {
|
|
67
75
|
throw new Error(`No storage plugin for protocol: ${protocol}`);
|
|
68
76
|
}
|
|
69
|
-
const { fileUrl } = await plugin.getDownloadUrl(storageUri);
|
|
77
|
+
const { fileUrl } = await plugin.getDownloadUrl(storageUri, context);
|
|
70
78
|
if (!fileUrl) {
|
|
71
79
|
throw new Error("Storage plugin returned empty fileUrl");
|
|
72
80
|
}
|
|
73
81
|
return fileUrl;
|
|
74
82
|
};
|
|
75
83
|
|
|
76
|
-
|
|
84
|
+
const resolveFileUrl = async (
|
|
85
|
+
storageUri: string | null,
|
|
86
|
+
context?: HotUpdaterContext<TContext>,
|
|
87
|
+
) => {
|
|
88
|
+
return resolveStoragePluginUrl(storageUri, context);
|
|
89
|
+
};
|
|
77
90
|
|
|
78
91
|
const database = options.database;
|
|
79
92
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
const core =
|
|
94
|
+
isDatabasePluginFactory(database) || isDatabasePlugin(database)
|
|
95
|
+
? createPluginDatabaseCore<TContext>(
|
|
96
|
+
isDatabasePluginFactory(database) ? database() : database,
|
|
97
|
+
resolveFileUrl,
|
|
98
|
+
)
|
|
99
|
+
: createOrmDatabaseCore<TContext>({
|
|
100
|
+
database,
|
|
101
|
+
resolveFileUrl,
|
|
102
|
+
});
|
|
89
103
|
|
|
90
|
-
|
|
104
|
+
const api = {
|
|
91
105
|
...core.api,
|
|
92
|
-
handler: createHandler(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
),
|
|
106
|
+
handler: createHandler(core.api, {
|
|
107
|
+
basePath,
|
|
108
|
+
routes: options.routes,
|
|
109
|
+
}),
|
|
96
110
|
adapterName: core.adapterName,
|
|
97
111
|
createMigrator: core.createMigrator,
|
|
98
112
|
generateSchema: core.generateSchema,
|
|
99
113
|
};
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
...api,
|
|
117
|
+
basePath,
|
|
118
|
+
handler: api.handler,
|
|
119
|
+
};
|
|
100
120
|
}
|