@hot-updater/server 0.21.5 → 0.21.6
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/index.cjs +8 -6
- package/dist/db/index.d.cts +8 -5
- package/dist/db/index.d.ts +8 -5
- package/dist/db/index.js +8 -6
- package/dist/handler.cjs +120 -111
- package/dist/handler.js +119 -111
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/node.cjs +51 -0
- package/dist/node.d.cts +25 -0
- package/dist/node.d.ts +25 -0
- package/dist/node.js +50 -0
- package/dist/schema/{v1.cjs → v0_21_0.cjs} +5 -5
- package/dist/schema/{v1.js → v0_21_0.js} +5 -5
- package/dist/types/index.d.cts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +15 -13
- package/src/db/index.spec.ts +14 -14
- package/src/db/index.ts +14 -5
- package/src/handler-standalone-integration.spec.ts +39 -33
- package/src/handler.ts +168 -153
- package/src/node.ts +104 -0
- package/src/schema/{v1.ts → v0_21_0.ts} +3 -3
- package/src/types/index.ts +1 -0
- package/dist/adapters/typeorm.cjs +0 -9
- package/dist/adapters/typeorm.d.cts +0 -1
- package/dist/adapters/typeorm.d.ts +0 -1
- package/dist/adapters/typeorm.js +0 -3
- package/src/adapters/typeorm.ts +0 -1
package/dist/db/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
2
|
const require_calculatePagination = require('../calculatePagination.cjs');
|
|
3
3
|
const require_handler = require('../handler.cjs');
|
|
4
|
-
const
|
|
4
|
+
const require_v0_21_0 = require('../schema/v0_21_0.cjs');
|
|
5
5
|
let __hot_updater_core = require("@hot-updater/core");
|
|
6
6
|
__hot_updater_core = require_rolldown_runtime.__toESM(__hot_updater_core);
|
|
7
7
|
let __hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
@@ -11,10 +11,10 @@ fumadb = require_rolldown_runtime.__toESM(fumadb);
|
|
|
11
11
|
|
|
12
12
|
//#region src/db/index.ts
|
|
13
13
|
const HotUpdaterDB = (0, fumadb.fumadb)({
|
|
14
|
-
namespace: "
|
|
15
|
-
schemas: [
|
|
14
|
+
namespace: "hot_updater",
|
|
15
|
+
schemas: [require_v0_21_0.v0_21_0]
|
|
16
16
|
});
|
|
17
|
-
function
|
|
17
|
+
function createHotUpdater(options) {
|
|
18
18
|
const client = HotUpdaterDB.client(options.database);
|
|
19
19
|
const cwd = options.cwd ?? process.cwd();
|
|
20
20
|
const storagePlugins = (options?.storagePlugins ?? []).map((plugin) => typeof plugin === "function" ? plugin({ cwd }) : plugin);
|
|
@@ -280,10 +280,12 @@ function hotUpdater(options) {
|
|
|
280
280
|
return {
|
|
281
281
|
...api,
|
|
282
282
|
handler: require_handler.createHandler(api, options?.basePath ? { basePath: options.basePath } : {}),
|
|
283
|
-
|
|
283
|
+
adapterName: client.adapter.name,
|
|
284
|
+
createMigrator: () => client.createMigrator(),
|
|
285
|
+
generateSchema: client.generateSchema
|
|
284
286
|
};
|
|
285
287
|
}
|
|
286
288
|
|
|
287
289
|
//#endregion
|
|
288
290
|
exports.HotUpdaterDB = HotUpdaterDB;
|
|
289
|
-
exports.
|
|
291
|
+
exports.createHotUpdater = createHotUpdater;
|
package/dist/db/index.d.cts
CHANGED
|
@@ -6,9 +6,9 @@ import { AppUpdateInfo, Bundle, GetBundlesArgs, UpdateInfo } from "@hot-updater/
|
|
|
6
6
|
import { StoragePlugin } from "@hot-updater/plugin-core";
|
|
7
7
|
|
|
8
8
|
//#region src/db/index.d.ts
|
|
9
|
-
declare const HotUpdaterDB: fumadb0.FumaDBFactory<fumadb_schema0.Schema<"
|
|
9
|
+
declare const HotUpdaterDB: fumadb0.FumaDBFactory<fumadb_schema0.Schema<"0.21.0", {
|
|
10
10
|
bundles: fumadb_schema0.Table<{
|
|
11
|
-
id: fumadb_schema0.IdColumn<"
|
|
11
|
+
id: fumadb_schema0.IdColumn<"uuid", string, string>;
|
|
12
12
|
platform: fumadb_schema0.Column<"string", string, string>;
|
|
13
13
|
should_force_update: fumadb_schema0.Column<"bool", boolean, boolean>;
|
|
14
14
|
enabled: fumadb_schema0.Column<"bool", boolean, boolean>;
|
|
@@ -46,8 +46,11 @@ interface DatabaseAPI {
|
|
|
46
46
|
}
|
|
47
47
|
type HotUpdaterAPI = DatabaseAPI & {
|
|
48
48
|
handler: (request: Request) => Promise<Response>;
|
|
49
|
-
|
|
49
|
+
adapterName: string;
|
|
50
|
+
createMigrator: HotUpdaterClient["createMigrator"];
|
|
51
|
+
generateSchema: HotUpdaterClient["generateSchema"];
|
|
50
52
|
};
|
|
53
|
+
type Migrator = ReturnType<HotUpdaterClient["createMigrator"]>;
|
|
51
54
|
type StoragePluginFactory = (args: {
|
|
52
55
|
cwd: string;
|
|
53
56
|
}) => StoragePlugin;
|
|
@@ -57,6 +60,6 @@ interface HotUpdaterOptions {
|
|
|
57
60
|
basePath?: string;
|
|
58
61
|
cwd?: string;
|
|
59
62
|
}
|
|
60
|
-
declare function
|
|
63
|
+
declare function createHotUpdater(options: HotUpdaterOptions): HotUpdaterAPI;
|
|
61
64
|
//#endregion
|
|
62
|
-
export { DatabaseAPI, DatabaseAdapter, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, StoragePluginFactory,
|
|
65
|
+
export { DatabaseAPI, DatabaseAdapter, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, Migrator, StoragePluginFactory, createHotUpdater };
|
package/dist/db/index.d.ts
CHANGED
|
@@ -6,9 +6,9 @@ import { InferFumaDB } from "fumadb";
|
|
|
6
6
|
import * as fumadb_schema0 from "fumadb/schema";
|
|
7
7
|
|
|
8
8
|
//#region src/db/index.d.ts
|
|
9
|
-
declare const HotUpdaterDB: fumadb0.FumaDBFactory<fumadb_schema0.Schema<"
|
|
9
|
+
declare const HotUpdaterDB: fumadb0.FumaDBFactory<fumadb_schema0.Schema<"0.21.0", {
|
|
10
10
|
bundles: fumadb_schema0.Table<{
|
|
11
|
-
id: fumadb_schema0.IdColumn<"
|
|
11
|
+
id: fumadb_schema0.IdColumn<"uuid", string, string>;
|
|
12
12
|
platform: fumadb_schema0.Column<"string", string, string>;
|
|
13
13
|
should_force_update: fumadb_schema0.Column<"bool", boolean, boolean>;
|
|
14
14
|
enabled: fumadb_schema0.Column<"bool", boolean, boolean>;
|
|
@@ -46,8 +46,11 @@ interface DatabaseAPI {
|
|
|
46
46
|
}
|
|
47
47
|
type HotUpdaterAPI = DatabaseAPI & {
|
|
48
48
|
handler: (request: Request) => Promise<Response>;
|
|
49
|
-
|
|
49
|
+
adapterName: string;
|
|
50
|
+
createMigrator: HotUpdaterClient["createMigrator"];
|
|
51
|
+
generateSchema: HotUpdaterClient["generateSchema"];
|
|
50
52
|
};
|
|
53
|
+
type Migrator = ReturnType<HotUpdaterClient["createMigrator"]>;
|
|
51
54
|
type StoragePluginFactory = (args: {
|
|
52
55
|
cwd: string;
|
|
53
56
|
}) => StoragePlugin;
|
|
@@ -57,6 +60,6 @@ interface HotUpdaterOptions {
|
|
|
57
60
|
basePath?: string;
|
|
58
61
|
cwd?: string;
|
|
59
62
|
}
|
|
60
|
-
declare function
|
|
63
|
+
declare function createHotUpdater(options: HotUpdaterOptions): HotUpdaterAPI;
|
|
61
64
|
//#endregion
|
|
62
|
-
export { DatabaseAPI, DatabaseAdapter, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, StoragePluginFactory,
|
|
65
|
+
export { DatabaseAPI, DatabaseAdapter, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, Migrator, StoragePluginFactory, createHotUpdater };
|
package/dist/db/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { calculatePagination } from "../calculatePagination.js";
|
|
2
2
|
import { createHandler } from "../handler.js";
|
|
3
|
-
import {
|
|
3
|
+
import { v0_21_0 } from "../schema/v0_21_0.js";
|
|
4
4
|
import { NIL_UUID } from "@hot-updater/core";
|
|
5
5
|
import { filterCompatibleAppVersions } from "@hot-updater/plugin-core";
|
|
6
6
|
import { fumadb } from "fumadb";
|
|
7
7
|
|
|
8
8
|
//#region src/db/index.ts
|
|
9
9
|
const HotUpdaterDB = fumadb({
|
|
10
|
-
namespace: "
|
|
11
|
-
schemas: [
|
|
10
|
+
namespace: "hot_updater",
|
|
11
|
+
schemas: [v0_21_0]
|
|
12
12
|
});
|
|
13
|
-
function
|
|
13
|
+
function createHotUpdater(options) {
|
|
14
14
|
const client = HotUpdaterDB.client(options.database);
|
|
15
15
|
const cwd = options.cwd ?? process.cwd();
|
|
16
16
|
const storagePlugins = (options?.storagePlugins ?? []).map((plugin) => typeof plugin === "function" ? plugin({ cwd }) : plugin);
|
|
@@ -276,9 +276,11 @@ function hotUpdater(options) {
|
|
|
276
276
|
return {
|
|
277
277
|
...api,
|
|
278
278
|
handler: createHandler(api, options?.basePath ? { basePath: options.basePath } : {}),
|
|
279
|
-
|
|
279
|
+
adapterName: client.adapter.name,
|
|
280
|
+
createMigrator: () => client.createMigrator(),
|
|
281
|
+
generateSchema: client.generateSchema
|
|
280
282
|
};
|
|
281
283
|
}
|
|
282
284
|
|
|
283
285
|
//#endregion
|
|
284
|
-
export { HotUpdaterDB,
|
|
286
|
+
export { HotUpdaterDB, createHotUpdater };
|
package/dist/handler.cjs
CHANGED
|
@@ -1,5 +1,107 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let rou3 = require("rou3");
|
|
3
|
+
rou3 = require_rolldown_runtime.__toESM(rou3);
|
|
1
4
|
|
|
2
5
|
//#region src/handler.ts
|
|
6
|
+
const handleUpdate = async (_params, request, api) => {
|
|
7
|
+
const body = await request.json();
|
|
8
|
+
const updateInfo = await api.getAppUpdateInfo(body);
|
|
9
|
+
return new Response(JSON.stringify(updateInfo), {
|
|
10
|
+
status: 200,
|
|
11
|
+
headers: { "Content-Type": "application/json" }
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
const handleFingerprintUpdate = async (params, _request, api) => {
|
|
15
|
+
const updateInfo = await api.getAppUpdateInfo({
|
|
16
|
+
_updateStrategy: "fingerprint",
|
|
17
|
+
platform: params.platform,
|
|
18
|
+
fingerprintHash: params.fingerprintHash,
|
|
19
|
+
channel: params.channel,
|
|
20
|
+
minBundleId: params.minBundleId,
|
|
21
|
+
bundleId: params.bundleId
|
|
22
|
+
});
|
|
23
|
+
return new Response(JSON.stringify(updateInfo), {
|
|
24
|
+
status: 200,
|
|
25
|
+
headers: { "Content-Type": "application/json" }
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
const handleAppVersionUpdate = async (params, _request, api) => {
|
|
29
|
+
const updateInfo = await api.getAppUpdateInfo({
|
|
30
|
+
_updateStrategy: "appVersion",
|
|
31
|
+
platform: params.platform,
|
|
32
|
+
appVersion: params.appVersion,
|
|
33
|
+
channel: params.channel,
|
|
34
|
+
minBundleId: params.minBundleId,
|
|
35
|
+
bundleId: params.bundleId
|
|
36
|
+
});
|
|
37
|
+
return new Response(JSON.stringify(updateInfo), {
|
|
38
|
+
status: 200,
|
|
39
|
+
headers: { "Content-Type": "application/json" }
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
const handleGetBundle = async (params, _request, api) => {
|
|
43
|
+
const bundle = await api.getBundleById(params.id);
|
|
44
|
+
if (!bundle) return new Response(JSON.stringify({ error: "Bundle not found" }), {
|
|
45
|
+
status: 404,
|
|
46
|
+
headers: { "Content-Type": "application/json" }
|
|
47
|
+
});
|
|
48
|
+
return new Response(JSON.stringify(bundle), {
|
|
49
|
+
status: 200,
|
|
50
|
+
headers: { "Content-Type": "application/json" }
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const handleGetBundles = async (_params, request, api) => {
|
|
54
|
+
const url = new URL(request.url);
|
|
55
|
+
const channel = url.searchParams.get("channel") ?? void 0;
|
|
56
|
+
const platform = url.searchParams.get("platform") ?? void 0;
|
|
57
|
+
const limit = Number(url.searchParams.get("limit")) || 50;
|
|
58
|
+
const offset = Number(url.searchParams.get("offset")) || 0;
|
|
59
|
+
const result = await api.getBundles({
|
|
60
|
+
where: {
|
|
61
|
+
...channel && { channel },
|
|
62
|
+
...platform && { platform }
|
|
63
|
+
},
|
|
64
|
+
limit,
|
|
65
|
+
offset
|
|
66
|
+
});
|
|
67
|
+
return new Response(JSON.stringify(result.data), {
|
|
68
|
+
status: 200,
|
|
69
|
+
headers: { "Content-Type": "application/json" }
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
const handleCreateBundles = async (_params, request, api) => {
|
|
73
|
+
const body = await request.json();
|
|
74
|
+
const bundles = Array.isArray(body) ? body : [body];
|
|
75
|
+
for (const bundle of bundles) await api.insertBundle(bundle);
|
|
76
|
+
return new Response(JSON.stringify({ success: true }), {
|
|
77
|
+
status: 201,
|
|
78
|
+
headers: { "Content-Type": "application/json" }
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
const handleDeleteBundle = async (params, _request, api) => {
|
|
82
|
+
await api.deleteBundleById(params.id);
|
|
83
|
+
return new Response(JSON.stringify({ success: true }), {
|
|
84
|
+
status: 200,
|
|
85
|
+
headers: { "Content-Type": "application/json" }
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
const handleGetChannels = async (_params, _request, api) => {
|
|
89
|
+
const channels = await api.getChannels();
|
|
90
|
+
return new Response(JSON.stringify({ channels }), {
|
|
91
|
+
status: 200,
|
|
92
|
+
headers: { "Content-Type": "application/json" }
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
const routes = {
|
|
96
|
+
update: handleUpdate,
|
|
97
|
+
fingerprintUpdate: handleFingerprintUpdate,
|
|
98
|
+
appVersionUpdate: handleAppVersionUpdate,
|
|
99
|
+
getBundle: handleGetBundle,
|
|
100
|
+
getBundles: handleGetBundles,
|
|
101
|
+
createBundles: handleCreateBundles,
|
|
102
|
+
deleteBundle: handleDeleteBundle,
|
|
103
|
+
getChannels: handleGetChannels
|
|
104
|
+
};
|
|
3
105
|
/**
|
|
4
106
|
* Creates a Web Standard Request handler for Hot Updater API
|
|
5
107
|
* This handler is framework-agnostic and works with any framework
|
|
@@ -7,123 +109,30 @@
|
|
|
7
109
|
*/
|
|
8
110
|
function createHandler(api, options = {}) {
|
|
9
111
|
const basePath = options.basePath ?? "/api";
|
|
112
|
+
const router = (0, rou3.createRouter)();
|
|
113
|
+
(0, rou3.addRoute)(router, "POST", "/update", "update");
|
|
114
|
+
(0, rou3.addRoute)(router, "GET", "/fingerprint/:platform/:fingerprintHash/:channel/:minBundleId/:bundleId", "fingerprintUpdate");
|
|
115
|
+
(0, rou3.addRoute)(router, "GET", "/app-version/:platform/:appVersion/:channel/:minBundleId/:bundleId", "appVersionUpdate");
|
|
116
|
+
(0, rou3.addRoute)(router, "GET", "/bundles/:id", "getBundle");
|
|
117
|
+
(0, rou3.addRoute)(router, "GET", "/bundles", "getBundles");
|
|
118
|
+
(0, rou3.addRoute)(router, "POST", "/bundles", "createBundles");
|
|
119
|
+
(0, rou3.addRoute)(router, "DELETE", "/bundles/:id", "deleteBundle");
|
|
120
|
+
(0, rou3.addRoute)(router, "GET", "/channels", "getChannels");
|
|
10
121
|
return async (request) => {
|
|
11
122
|
try {
|
|
12
|
-
const
|
|
13
|
-
const path = url.pathname;
|
|
123
|
+
const path = new URL(request.url).pathname;
|
|
14
124
|
const method = request.method;
|
|
15
|
-
const
|
|
16
|
-
if (
|
|
17
|
-
const body = await request.json();
|
|
18
|
-
const updateInfo = await api.getAppUpdateInfo(body);
|
|
19
|
-
if (!updateInfo) return new Response(JSON.stringify(null), {
|
|
20
|
-
status: 200,
|
|
21
|
-
headers: { "Content-Type": "application/json" }
|
|
22
|
-
});
|
|
23
|
-
return new Response(JSON.stringify(updateInfo), {
|
|
24
|
-
status: 200,
|
|
25
|
-
headers: { "Content-Type": "application/json" }
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
const fingerprintMatch = routePath.match(/^\/fingerprint\/([^/]+)\/([^/]+)\/([^/]+)\/([^/]+)\/([^/]+)$/);
|
|
29
|
-
if (fingerprintMatch && method === "GET") {
|
|
30
|
-
const [, platform, fingerprintHash, channel, minBundleId, bundleId] = fingerprintMatch;
|
|
31
|
-
const updateInfo = await api.getAppUpdateInfo({
|
|
32
|
-
_updateStrategy: "fingerprint",
|
|
33
|
-
platform,
|
|
34
|
-
fingerprintHash,
|
|
35
|
-
channel,
|
|
36
|
-
minBundleId,
|
|
37
|
-
bundleId
|
|
38
|
-
});
|
|
39
|
-
if (!updateInfo) return new Response(JSON.stringify(null), {
|
|
40
|
-
status: 200,
|
|
41
|
-
headers: { "Content-Type": "application/json" }
|
|
42
|
-
});
|
|
43
|
-
return new Response(JSON.stringify(updateInfo), {
|
|
44
|
-
status: 200,
|
|
45
|
-
headers: { "Content-Type": "application/json" }
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
const appVersionMatch = routePath.match(/^\/app-version\/([^/]+)\/([^/]+)\/([^/]+)\/([^/]+)\/([^/]+)$/);
|
|
49
|
-
if (appVersionMatch && method === "GET") {
|
|
50
|
-
const [, platform, appVersion, channel, minBundleId, bundleId] = appVersionMatch;
|
|
51
|
-
const updateInfo = await api.getAppUpdateInfo({
|
|
52
|
-
_updateStrategy: "appVersion",
|
|
53
|
-
platform,
|
|
54
|
-
appVersion,
|
|
55
|
-
channel,
|
|
56
|
-
minBundleId,
|
|
57
|
-
bundleId
|
|
58
|
-
});
|
|
59
|
-
if (!updateInfo) return new Response(JSON.stringify(null), {
|
|
60
|
-
status: 200,
|
|
61
|
-
headers: { "Content-Type": "application/json" }
|
|
62
|
-
});
|
|
63
|
-
return new Response(JSON.stringify(updateInfo), {
|
|
64
|
-
status: 200,
|
|
65
|
-
headers: { "Content-Type": "application/json" }
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
const getBundleMatch = routePath.match(/^\/bundles\/([^/]+)$/);
|
|
69
|
-
if (getBundleMatch && method === "GET") {
|
|
70
|
-
const id = getBundleMatch[1];
|
|
71
|
-
const bundle = await api.getBundleById(id);
|
|
72
|
-
if (!bundle) return new Response(JSON.stringify({ error: "Bundle not found" }), {
|
|
73
|
-
status: 404,
|
|
74
|
-
headers: { "Content-Type": "application/json" }
|
|
75
|
-
});
|
|
76
|
-
return new Response(JSON.stringify(bundle), {
|
|
77
|
-
status: 200,
|
|
78
|
-
headers: { "Content-Type": "application/json" }
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
if (routePath === "/bundles" && method === "GET") {
|
|
82
|
-
const channel = url.searchParams.get("channel") ?? void 0;
|
|
83
|
-
const platform = url.searchParams.get("platform") ?? void 0;
|
|
84
|
-
const limit = Number(url.searchParams.get("limit")) || 50;
|
|
85
|
-
const offset = Number(url.searchParams.get("offset")) || 0;
|
|
86
|
-
const result = await api.getBundles({
|
|
87
|
-
where: {
|
|
88
|
-
...channel && { channel },
|
|
89
|
-
...platform && { platform }
|
|
90
|
-
},
|
|
91
|
-
limit,
|
|
92
|
-
offset
|
|
93
|
-
});
|
|
94
|
-
return new Response(JSON.stringify(result.data), {
|
|
95
|
-
status: 200,
|
|
96
|
-
headers: { "Content-Type": "application/json" }
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
if (routePath === "/bundles" && method === "POST") {
|
|
100
|
-
const body = await request.json();
|
|
101
|
-
const bundles = Array.isArray(body) ? body : [body];
|
|
102
|
-
for (const bundle of bundles) await api.insertBundle(bundle);
|
|
103
|
-
return new Response(JSON.stringify({ success: true }), {
|
|
104
|
-
status: 201,
|
|
105
|
-
headers: { "Content-Type": "application/json" }
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
if (routePath.startsWith("/bundles/") && method === "DELETE") {
|
|
109
|
-
const id = routePath.slice(9);
|
|
110
|
-
await api.deleteBundleById(id);
|
|
111
|
-
return new Response(JSON.stringify({ success: true }), {
|
|
112
|
-
status: 200,
|
|
113
|
-
headers: { "Content-Type": "application/json" }
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
if (routePath === "/channels" && method === "GET") {
|
|
117
|
-
const channels = await api.getChannels();
|
|
118
|
-
return new Response(JSON.stringify({ channels }), {
|
|
119
|
-
status: 200,
|
|
120
|
-
headers: { "Content-Type": "application/json" }
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
return new Response(JSON.stringify({ error: "Not found" }), {
|
|
125
|
+
const match = (0, rou3.findRoute)(router, method, path.startsWith(basePath) ? path.slice(basePath.length) : path);
|
|
126
|
+
if (!match) return new Response(JSON.stringify({ error: "Not found" }), {
|
|
124
127
|
status: 404,
|
|
125
128
|
headers: { "Content-Type": "application/json" }
|
|
126
129
|
});
|
|
130
|
+
const handler = routes[match.data];
|
|
131
|
+
if (!handler) return new Response(JSON.stringify({ error: "Handler not found" }), {
|
|
132
|
+
status: 500,
|
|
133
|
+
headers: { "Content-Type": "application/json" }
|
|
134
|
+
});
|
|
135
|
+
return await handler(match.params || {}, request, api);
|
|
127
136
|
} catch (error) {
|
|
128
137
|
console.error("Hot Updater handler error:", error);
|
|
129
138
|
return new Response(JSON.stringify({
|
package/dist/handler.js
CHANGED
|
@@ -1,4 +1,105 @@
|
|
|
1
|
+
import { addRoute, createRouter, findRoute } from "rou3";
|
|
2
|
+
|
|
1
3
|
//#region src/handler.ts
|
|
4
|
+
const handleUpdate = async (_params, request, api) => {
|
|
5
|
+
const body = await request.json();
|
|
6
|
+
const updateInfo = await api.getAppUpdateInfo(body);
|
|
7
|
+
return new Response(JSON.stringify(updateInfo), {
|
|
8
|
+
status: 200,
|
|
9
|
+
headers: { "Content-Type": "application/json" }
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
const handleFingerprintUpdate = async (params, _request, api) => {
|
|
13
|
+
const updateInfo = await api.getAppUpdateInfo({
|
|
14
|
+
_updateStrategy: "fingerprint",
|
|
15
|
+
platform: params.platform,
|
|
16
|
+
fingerprintHash: params.fingerprintHash,
|
|
17
|
+
channel: params.channel,
|
|
18
|
+
minBundleId: params.minBundleId,
|
|
19
|
+
bundleId: params.bundleId
|
|
20
|
+
});
|
|
21
|
+
return new Response(JSON.stringify(updateInfo), {
|
|
22
|
+
status: 200,
|
|
23
|
+
headers: { "Content-Type": "application/json" }
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
const handleAppVersionUpdate = async (params, _request, api) => {
|
|
27
|
+
const updateInfo = await api.getAppUpdateInfo({
|
|
28
|
+
_updateStrategy: "appVersion",
|
|
29
|
+
platform: params.platform,
|
|
30
|
+
appVersion: params.appVersion,
|
|
31
|
+
channel: params.channel,
|
|
32
|
+
minBundleId: params.minBundleId,
|
|
33
|
+
bundleId: params.bundleId
|
|
34
|
+
});
|
|
35
|
+
return new Response(JSON.stringify(updateInfo), {
|
|
36
|
+
status: 200,
|
|
37
|
+
headers: { "Content-Type": "application/json" }
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
const handleGetBundle = async (params, _request, api) => {
|
|
41
|
+
const bundle = await api.getBundleById(params.id);
|
|
42
|
+
if (!bundle) return new Response(JSON.stringify({ error: "Bundle not found" }), {
|
|
43
|
+
status: 404,
|
|
44
|
+
headers: { "Content-Type": "application/json" }
|
|
45
|
+
});
|
|
46
|
+
return new Response(JSON.stringify(bundle), {
|
|
47
|
+
status: 200,
|
|
48
|
+
headers: { "Content-Type": "application/json" }
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const handleGetBundles = async (_params, request, api) => {
|
|
52
|
+
const url = new URL(request.url);
|
|
53
|
+
const channel = url.searchParams.get("channel") ?? void 0;
|
|
54
|
+
const platform = url.searchParams.get("platform") ?? void 0;
|
|
55
|
+
const limit = Number(url.searchParams.get("limit")) || 50;
|
|
56
|
+
const offset = Number(url.searchParams.get("offset")) || 0;
|
|
57
|
+
const result = await api.getBundles({
|
|
58
|
+
where: {
|
|
59
|
+
...channel && { channel },
|
|
60
|
+
...platform && { platform }
|
|
61
|
+
},
|
|
62
|
+
limit,
|
|
63
|
+
offset
|
|
64
|
+
});
|
|
65
|
+
return new Response(JSON.stringify(result.data), {
|
|
66
|
+
status: 200,
|
|
67
|
+
headers: { "Content-Type": "application/json" }
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const handleCreateBundles = async (_params, request, api) => {
|
|
71
|
+
const body = await request.json();
|
|
72
|
+
const bundles = Array.isArray(body) ? body : [body];
|
|
73
|
+
for (const bundle of bundles) await api.insertBundle(bundle);
|
|
74
|
+
return new Response(JSON.stringify({ success: true }), {
|
|
75
|
+
status: 201,
|
|
76
|
+
headers: { "Content-Type": "application/json" }
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
const handleDeleteBundle = async (params, _request, api) => {
|
|
80
|
+
await api.deleteBundleById(params.id);
|
|
81
|
+
return new Response(JSON.stringify({ success: true }), {
|
|
82
|
+
status: 200,
|
|
83
|
+
headers: { "Content-Type": "application/json" }
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
const handleGetChannels = async (_params, _request, api) => {
|
|
87
|
+
const channels = await api.getChannels();
|
|
88
|
+
return new Response(JSON.stringify({ channels }), {
|
|
89
|
+
status: 200,
|
|
90
|
+
headers: { "Content-Type": "application/json" }
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
const routes = {
|
|
94
|
+
update: handleUpdate,
|
|
95
|
+
fingerprintUpdate: handleFingerprintUpdate,
|
|
96
|
+
appVersionUpdate: handleAppVersionUpdate,
|
|
97
|
+
getBundle: handleGetBundle,
|
|
98
|
+
getBundles: handleGetBundles,
|
|
99
|
+
createBundles: handleCreateBundles,
|
|
100
|
+
deleteBundle: handleDeleteBundle,
|
|
101
|
+
getChannels: handleGetChannels
|
|
102
|
+
};
|
|
2
103
|
/**
|
|
3
104
|
* Creates a Web Standard Request handler for Hot Updater API
|
|
4
105
|
* This handler is framework-agnostic and works with any framework
|
|
@@ -6,123 +107,30 @@
|
|
|
6
107
|
*/
|
|
7
108
|
function createHandler(api, options = {}) {
|
|
8
109
|
const basePath = options.basePath ?? "/api";
|
|
110
|
+
const router = createRouter();
|
|
111
|
+
addRoute(router, "POST", "/update", "update");
|
|
112
|
+
addRoute(router, "GET", "/fingerprint/:platform/:fingerprintHash/:channel/:minBundleId/:bundleId", "fingerprintUpdate");
|
|
113
|
+
addRoute(router, "GET", "/app-version/:platform/:appVersion/:channel/:minBundleId/:bundleId", "appVersionUpdate");
|
|
114
|
+
addRoute(router, "GET", "/bundles/:id", "getBundle");
|
|
115
|
+
addRoute(router, "GET", "/bundles", "getBundles");
|
|
116
|
+
addRoute(router, "POST", "/bundles", "createBundles");
|
|
117
|
+
addRoute(router, "DELETE", "/bundles/:id", "deleteBundle");
|
|
118
|
+
addRoute(router, "GET", "/channels", "getChannels");
|
|
9
119
|
return async (request) => {
|
|
10
120
|
try {
|
|
11
|
-
const
|
|
12
|
-
const path = url.pathname;
|
|
121
|
+
const path = new URL(request.url).pathname;
|
|
13
122
|
const method = request.method;
|
|
14
|
-
const
|
|
15
|
-
if (
|
|
16
|
-
const body = await request.json();
|
|
17
|
-
const updateInfo = await api.getAppUpdateInfo(body);
|
|
18
|
-
if (!updateInfo) return new Response(JSON.stringify(null), {
|
|
19
|
-
status: 200,
|
|
20
|
-
headers: { "Content-Type": "application/json" }
|
|
21
|
-
});
|
|
22
|
-
return new Response(JSON.stringify(updateInfo), {
|
|
23
|
-
status: 200,
|
|
24
|
-
headers: { "Content-Type": "application/json" }
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
const fingerprintMatch = routePath.match(/^\/fingerprint\/([^/]+)\/([^/]+)\/([^/]+)\/([^/]+)\/([^/]+)$/);
|
|
28
|
-
if (fingerprintMatch && method === "GET") {
|
|
29
|
-
const [, platform, fingerprintHash, channel, minBundleId, bundleId] = fingerprintMatch;
|
|
30
|
-
const updateInfo = await api.getAppUpdateInfo({
|
|
31
|
-
_updateStrategy: "fingerprint",
|
|
32
|
-
platform,
|
|
33
|
-
fingerprintHash,
|
|
34
|
-
channel,
|
|
35
|
-
minBundleId,
|
|
36
|
-
bundleId
|
|
37
|
-
});
|
|
38
|
-
if (!updateInfo) return new Response(JSON.stringify(null), {
|
|
39
|
-
status: 200,
|
|
40
|
-
headers: { "Content-Type": "application/json" }
|
|
41
|
-
});
|
|
42
|
-
return new Response(JSON.stringify(updateInfo), {
|
|
43
|
-
status: 200,
|
|
44
|
-
headers: { "Content-Type": "application/json" }
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
const appVersionMatch = routePath.match(/^\/app-version\/([^/]+)\/([^/]+)\/([^/]+)\/([^/]+)\/([^/]+)$/);
|
|
48
|
-
if (appVersionMatch && method === "GET") {
|
|
49
|
-
const [, platform, appVersion, channel, minBundleId, bundleId] = appVersionMatch;
|
|
50
|
-
const updateInfo = await api.getAppUpdateInfo({
|
|
51
|
-
_updateStrategy: "appVersion",
|
|
52
|
-
platform,
|
|
53
|
-
appVersion,
|
|
54
|
-
channel,
|
|
55
|
-
minBundleId,
|
|
56
|
-
bundleId
|
|
57
|
-
});
|
|
58
|
-
if (!updateInfo) return new Response(JSON.stringify(null), {
|
|
59
|
-
status: 200,
|
|
60
|
-
headers: { "Content-Type": "application/json" }
|
|
61
|
-
});
|
|
62
|
-
return new Response(JSON.stringify(updateInfo), {
|
|
63
|
-
status: 200,
|
|
64
|
-
headers: { "Content-Type": "application/json" }
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
const getBundleMatch = routePath.match(/^\/bundles\/([^/]+)$/);
|
|
68
|
-
if (getBundleMatch && method === "GET") {
|
|
69
|
-
const id = getBundleMatch[1];
|
|
70
|
-
const bundle = await api.getBundleById(id);
|
|
71
|
-
if (!bundle) return new Response(JSON.stringify({ error: "Bundle not found" }), {
|
|
72
|
-
status: 404,
|
|
73
|
-
headers: { "Content-Type": "application/json" }
|
|
74
|
-
});
|
|
75
|
-
return new Response(JSON.stringify(bundle), {
|
|
76
|
-
status: 200,
|
|
77
|
-
headers: { "Content-Type": "application/json" }
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
if (routePath === "/bundles" && method === "GET") {
|
|
81
|
-
const channel = url.searchParams.get("channel") ?? void 0;
|
|
82
|
-
const platform = url.searchParams.get("platform") ?? void 0;
|
|
83
|
-
const limit = Number(url.searchParams.get("limit")) || 50;
|
|
84
|
-
const offset = Number(url.searchParams.get("offset")) || 0;
|
|
85
|
-
const result = await api.getBundles({
|
|
86
|
-
where: {
|
|
87
|
-
...channel && { channel },
|
|
88
|
-
...platform && { platform }
|
|
89
|
-
},
|
|
90
|
-
limit,
|
|
91
|
-
offset
|
|
92
|
-
});
|
|
93
|
-
return new Response(JSON.stringify(result.data), {
|
|
94
|
-
status: 200,
|
|
95
|
-
headers: { "Content-Type": "application/json" }
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
if (routePath === "/bundles" && method === "POST") {
|
|
99
|
-
const body = await request.json();
|
|
100
|
-
const bundles = Array.isArray(body) ? body : [body];
|
|
101
|
-
for (const bundle of bundles) await api.insertBundle(bundle);
|
|
102
|
-
return new Response(JSON.stringify({ success: true }), {
|
|
103
|
-
status: 201,
|
|
104
|
-
headers: { "Content-Type": "application/json" }
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
if (routePath.startsWith("/bundles/") && method === "DELETE") {
|
|
108
|
-
const id = routePath.slice(9);
|
|
109
|
-
await api.deleteBundleById(id);
|
|
110
|
-
return new Response(JSON.stringify({ success: true }), {
|
|
111
|
-
status: 200,
|
|
112
|
-
headers: { "Content-Type": "application/json" }
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
if (routePath === "/channels" && method === "GET") {
|
|
116
|
-
const channels = await api.getChannels();
|
|
117
|
-
return new Response(JSON.stringify({ channels }), {
|
|
118
|
-
status: 200,
|
|
119
|
-
headers: { "Content-Type": "application/json" }
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
return new Response(JSON.stringify({ error: "Not found" }), {
|
|
123
|
+
const match = findRoute(router, method, path.startsWith(basePath) ? path.slice(basePath.length) : path);
|
|
124
|
+
if (!match) return new Response(JSON.stringify({ error: "Not found" }), {
|
|
123
125
|
status: 404,
|
|
124
126
|
headers: { "Content-Type": "application/json" }
|
|
125
127
|
});
|
|
128
|
+
const handler = routes[match.data];
|
|
129
|
+
if (!handler) return new Response(JSON.stringify({ error: "Handler not found" }), {
|
|
130
|
+
status: 500,
|
|
131
|
+
headers: { "Content-Type": "application/json" }
|
|
132
|
+
});
|
|
133
|
+
return await handler(match.params || {}, request, api);
|
|
126
134
|
} catch (error) {
|
|
127
135
|
console.error("Hot Updater handler error:", error);
|
|
128
136
|
return new Response(JSON.stringify({
|
package/dist/index.cjs
CHANGED
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Bundle, PaginatedResult, PaginationInfo, PaginationOptions } from "./types/index.cjs";
|
|
2
|
-
import { DatabaseAPI, DatabaseAdapter, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, StoragePluginFactory,
|
|
2
|
+
import { DatabaseAPI, DatabaseAdapter, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, Migrator, StoragePluginFactory, createHotUpdater } from "./db/index.cjs";
|
|
3
3
|
import { HandlerAPI, HandlerOptions, createHandler } from "./handler.cjs";
|
|
4
|
-
export { Bundle, DatabaseAPI, DatabaseAdapter, HandlerAPI, HandlerOptions, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, PaginatedResult, PaginationInfo, PaginationOptions, StoragePluginFactory, createHandler,
|
|
4
|
+
export { Bundle, DatabaseAPI, DatabaseAdapter, HandlerAPI, HandlerOptions, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, Migrator, PaginatedResult, PaginationInfo, PaginationOptions, StoragePluginFactory, createHandler, createHotUpdater };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Bundle, PaginatedResult, PaginationInfo, PaginationOptions } from "./types/index.js";
|
|
2
|
-
import { DatabaseAPI, DatabaseAdapter, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, StoragePluginFactory,
|
|
2
|
+
import { DatabaseAPI, DatabaseAdapter, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, Migrator, StoragePluginFactory, createHotUpdater } from "./db/index.js";
|
|
3
3
|
import { HandlerAPI, HandlerOptions, createHandler } from "./handler.js";
|
|
4
|
-
export { Bundle, DatabaseAPI, DatabaseAdapter, HandlerAPI, HandlerOptions, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, PaginatedResult, PaginationInfo, PaginationOptions, StoragePluginFactory, createHandler,
|
|
4
|
+
export { Bundle, DatabaseAPI, DatabaseAdapter, HandlerAPI, HandlerOptions, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, HotUpdaterOptions, Migrator, PaginatedResult, PaginationInfo, PaginationOptions, StoragePluginFactory, createHandler, createHotUpdater };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { createHandler } from "./handler.js";
|
|
2
|
-
import { HotUpdaterDB,
|
|
2
|
+
import { HotUpdaterDB, createHotUpdater } from "./db/index.js";
|
|
3
3
|
|
|
4
|
-
export { HotUpdaterDB, createHandler,
|
|
4
|
+
export { HotUpdaterDB, createHandler, createHotUpdater };
|