@hot-updater/server 0.27.1 → 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/dist/db/ormCore.js
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
import { calculatePagination } from "../calculatePagination.js";
|
|
2
|
-
import { v0_21_0 } from "../schema/v0_21_0.js";
|
|
3
|
-
import { NIL_UUID } from "@hot-updater/core";
|
|
4
|
-
import { filterCompatibleAppVersions } from "@hot-updater/plugin-core";
|
|
5
|
-
import { fumadb } from "fumadb";
|
|
6
|
-
|
|
7
|
-
//#region src/db/ormCore.ts
|
|
8
|
-
const HotUpdaterDB = fumadb({
|
|
9
|
-
namespace: "hot_updater",
|
|
10
|
-
schemas: [v0_21_0]
|
|
11
|
-
});
|
|
12
|
-
function createOrmDatabaseCore({ database, resolveFileUrl }) {
|
|
13
|
-
const client = HotUpdaterDB.client(database);
|
|
14
|
-
return {
|
|
15
|
-
api: {
|
|
16
|
-
async getBundleById(id) {
|
|
17
|
-
const version = await client.version();
|
|
18
|
-
const result = await client.orm(version).findFirst("bundles", {
|
|
19
|
-
select: [
|
|
20
|
-
"id",
|
|
21
|
-
"platform",
|
|
22
|
-
"should_force_update",
|
|
23
|
-
"enabled",
|
|
24
|
-
"file_hash",
|
|
25
|
-
"git_commit_hash",
|
|
26
|
-
"message",
|
|
27
|
-
"channel",
|
|
28
|
-
"storage_uri",
|
|
29
|
-
"target_app_version",
|
|
30
|
-
"fingerprint_hash",
|
|
31
|
-
"metadata"
|
|
32
|
-
],
|
|
33
|
-
where: (b) => b("id", "=", id)
|
|
34
|
-
});
|
|
35
|
-
if (!result) return null;
|
|
36
|
-
return {
|
|
37
|
-
id: result.id,
|
|
38
|
-
platform: result.platform,
|
|
39
|
-
shouldForceUpdate: Boolean(result.should_force_update),
|
|
40
|
-
enabled: Boolean(result.enabled),
|
|
41
|
-
fileHash: result.file_hash,
|
|
42
|
-
gitCommitHash: result.git_commit_hash ?? null,
|
|
43
|
-
message: result.message ?? null,
|
|
44
|
-
channel: result.channel,
|
|
45
|
-
storageUri: result.storage_uri,
|
|
46
|
-
targetAppVersion: result.target_app_version ?? null,
|
|
47
|
-
fingerprintHash: result.fingerprint_hash ?? null
|
|
48
|
-
};
|
|
49
|
-
},
|
|
50
|
-
async getUpdateInfo(args) {
|
|
51
|
-
const version = await client.version();
|
|
52
|
-
const orm = client.orm(version);
|
|
53
|
-
const toUpdateInfo = (row, status) => ({
|
|
54
|
-
id: row.id,
|
|
55
|
-
shouldForceUpdate: status === "ROLLBACK" ? true : Boolean(row.should_force_update),
|
|
56
|
-
message: row.message ?? null,
|
|
57
|
-
status,
|
|
58
|
-
storageUri: row.storage_uri ?? null,
|
|
59
|
-
fileHash: row.file_hash ?? null
|
|
60
|
-
});
|
|
61
|
-
const INIT_BUNDLE_ROLLBACK_UPDATE_INFO = {
|
|
62
|
-
id: NIL_UUID,
|
|
63
|
-
message: null,
|
|
64
|
-
shouldForceUpdate: true,
|
|
65
|
-
status: "ROLLBACK",
|
|
66
|
-
storageUri: null,
|
|
67
|
-
fileHash: null
|
|
68
|
-
};
|
|
69
|
-
const appVersionStrategy = async ({ platform, appVersion, bundleId, minBundleId = NIL_UUID, channel = "production" }) => {
|
|
70
|
-
const versionRows = await orm.findMany("bundles", {
|
|
71
|
-
select: ["target_app_version"],
|
|
72
|
-
where: (b) => b.and(b("platform", "=", platform))
|
|
73
|
-
});
|
|
74
|
-
const compatibleVersions = filterCompatibleAppVersions(Array.from(new Set((versionRows ?? []).map((r) => r.target_app_version).filter((v) => Boolean(v)))), appVersion);
|
|
75
|
-
const candidates = ((compatibleVersions.length === 0 ? [] : await orm.findMany("bundles", {
|
|
76
|
-
select: [
|
|
77
|
-
"id",
|
|
78
|
-
"should_force_update",
|
|
79
|
-
"message",
|
|
80
|
-
"storage_uri",
|
|
81
|
-
"file_hash",
|
|
82
|
-
"channel",
|
|
83
|
-
"target_app_version",
|
|
84
|
-
"enabled"
|
|
85
|
-
],
|
|
86
|
-
where: (b) => b.and(b("enabled", "=", true), b("platform", "=", platform), b("id", ">=", minBundleId ?? NIL_UUID), b("channel", "=", channel), b.isNotNull("target_app_version"))
|
|
87
|
-
})) ?? []).filter((r) => r.target_app_version ? compatibleVersions.includes(r.target_app_version) : false);
|
|
88
|
-
const byIdDesc = (a, b) => b.id.localeCompare(a.id);
|
|
89
|
-
const sorted = (candidates ?? []).slice().sort(byIdDesc);
|
|
90
|
-
const latestCandidate = sorted[0] ?? null;
|
|
91
|
-
const currentBundle = sorted.find((b) => b.id === bundleId);
|
|
92
|
-
const updateCandidate = sorted.find((b) => b.id.localeCompare(bundleId) > 0) ?? null;
|
|
93
|
-
const rollbackCandidate = sorted.find((b) => b.id.localeCompare(bundleId) < 0) ?? null;
|
|
94
|
-
if (bundleId === NIL_UUID) {
|
|
95
|
-
if (latestCandidate && latestCandidate.id !== bundleId) return toUpdateInfo(latestCandidate, "UPDATE");
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
if (currentBundle) {
|
|
99
|
-
if (latestCandidate && latestCandidate.id.localeCompare(currentBundle.id) > 0) return toUpdateInfo(latestCandidate, "UPDATE");
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
if (updateCandidate) return toUpdateInfo(updateCandidate, "UPDATE");
|
|
103
|
-
if (rollbackCandidate) return toUpdateInfo(rollbackCandidate, "ROLLBACK");
|
|
104
|
-
if (minBundleId && bundleId.localeCompare(minBundleId) <= 0) return null;
|
|
105
|
-
return INIT_BUNDLE_ROLLBACK_UPDATE_INFO;
|
|
106
|
-
};
|
|
107
|
-
const fingerprintStrategy = async ({ platform, fingerprintHash, bundleId, minBundleId = NIL_UUID, channel = "production" }) => {
|
|
108
|
-
const candidates = await orm.findMany("bundles", {
|
|
109
|
-
select: [
|
|
110
|
-
"id",
|
|
111
|
-
"should_force_update",
|
|
112
|
-
"message",
|
|
113
|
-
"storage_uri",
|
|
114
|
-
"file_hash",
|
|
115
|
-
"channel",
|
|
116
|
-
"fingerprint_hash",
|
|
117
|
-
"enabled"
|
|
118
|
-
],
|
|
119
|
-
where: (b) => b.and(b("enabled", "=", true), b("platform", "=", platform), b("id", ">=", minBundleId ?? NIL_UUID), b("channel", "=", channel), b("fingerprint_hash", "=", fingerprintHash))
|
|
120
|
-
});
|
|
121
|
-
const byIdDesc = (a, b) => b.id.localeCompare(a.id);
|
|
122
|
-
const sorted = (candidates ?? []).slice().sort(byIdDesc);
|
|
123
|
-
const latestCandidate = sorted[0] ?? null;
|
|
124
|
-
const currentBundle = sorted.find((b) => b.id === bundleId);
|
|
125
|
-
const updateCandidate = sorted.find((b) => b.id.localeCompare(bundleId) > 0) ?? null;
|
|
126
|
-
const rollbackCandidate = sorted.find((b) => b.id.localeCompare(bundleId) < 0) ?? null;
|
|
127
|
-
if (bundleId === NIL_UUID) {
|
|
128
|
-
if (latestCandidate && latestCandidate.id !== bundleId) return toUpdateInfo(latestCandidate, "UPDATE");
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
if (currentBundle) {
|
|
132
|
-
if (latestCandidate && latestCandidate.id.localeCompare(currentBundle.id) > 0) return toUpdateInfo(latestCandidate, "UPDATE");
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
if (updateCandidate) return toUpdateInfo(updateCandidate, "UPDATE");
|
|
136
|
-
if (rollbackCandidate) return toUpdateInfo(rollbackCandidate, "ROLLBACK");
|
|
137
|
-
if (minBundleId && bundleId.localeCompare(minBundleId) <= 0) return null;
|
|
138
|
-
return INIT_BUNDLE_ROLLBACK_UPDATE_INFO;
|
|
139
|
-
};
|
|
140
|
-
if (args._updateStrategy === "appVersion") return appVersionStrategy(args);
|
|
141
|
-
if (args._updateStrategy === "fingerprint") return fingerprintStrategy(args);
|
|
142
|
-
return null;
|
|
143
|
-
},
|
|
144
|
-
async getAppUpdateInfo(args) {
|
|
145
|
-
const info = await this.getUpdateInfo(args);
|
|
146
|
-
if (!info) return null;
|
|
147
|
-
const { storageUri,...rest } = info;
|
|
148
|
-
const fileUrl = await resolveFileUrl(storageUri ?? null);
|
|
149
|
-
return {
|
|
150
|
-
...rest,
|
|
151
|
-
fileUrl
|
|
152
|
-
};
|
|
153
|
-
},
|
|
154
|
-
async getChannels() {
|
|
155
|
-
const version = await client.version();
|
|
156
|
-
const rows = await client.orm(version).findMany("bundles", { select: ["channel"] });
|
|
157
|
-
const set = new Set(rows?.map((r) => r.channel) ?? []);
|
|
158
|
-
return Array.from(set);
|
|
159
|
-
},
|
|
160
|
-
async getBundles(options) {
|
|
161
|
-
const version = await client.version();
|
|
162
|
-
const orm = client.orm(version);
|
|
163
|
-
const { where, limit, offset } = options;
|
|
164
|
-
const all = (await orm.findMany("bundles", {
|
|
165
|
-
select: [
|
|
166
|
-
"id",
|
|
167
|
-
"platform",
|
|
168
|
-
"should_force_update",
|
|
169
|
-
"enabled",
|
|
170
|
-
"file_hash",
|
|
171
|
-
"git_commit_hash",
|
|
172
|
-
"message",
|
|
173
|
-
"channel",
|
|
174
|
-
"storage_uri",
|
|
175
|
-
"target_app_version",
|
|
176
|
-
"fingerprint_hash",
|
|
177
|
-
"metadata"
|
|
178
|
-
],
|
|
179
|
-
where: (b) => {
|
|
180
|
-
const conditions = [];
|
|
181
|
-
if (where?.channel) conditions.push(b("channel", "=", where.channel));
|
|
182
|
-
if (where?.platform) conditions.push(b("platform", "=", where.platform));
|
|
183
|
-
return conditions.length > 0 ? b.and(...conditions) : true;
|
|
184
|
-
}
|
|
185
|
-
})).map((r) => ({
|
|
186
|
-
id: r.id,
|
|
187
|
-
platform: r.platform,
|
|
188
|
-
shouldForceUpdate: Boolean(r.should_force_update),
|
|
189
|
-
enabled: Boolean(r.enabled),
|
|
190
|
-
fileHash: r.file_hash,
|
|
191
|
-
gitCommitHash: r.git_commit_hash ?? null,
|
|
192
|
-
message: r.message ?? null,
|
|
193
|
-
channel: r.channel,
|
|
194
|
-
storageUri: r.storage_uri,
|
|
195
|
-
targetAppVersion: r.target_app_version ?? null,
|
|
196
|
-
fingerprintHash: r.fingerprint_hash ?? null
|
|
197
|
-
})).sort((a, b) => b.id.localeCompare(a.id));
|
|
198
|
-
const total = all.length;
|
|
199
|
-
return {
|
|
200
|
-
data: all.slice(offset, offset + limit),
|
|
201
|
-
pagination: calculatePagination(total, {
|
|
202
|
-
limit,
|
|
203
|
-
offset
|
|
204
|
-
})
|
|
205
|
-
};
|
|
206
|
-
},
|
|
207
|
-
async insertBundle(bundle) {
|
|
208
|
-
const version = await client.version();
|
|
209
|
-
const orm = client.orm(version);
|
|
210
|
-
const values = {
|
|
211
|
-
id: bundle.id,
|
|
212
|
-
platform: bundle.platform,
|
|
213
|
-
should_force_update: bundle.shouldForceUpdate,
|
|
214
|
-
enabled: bundle.enabled,
|
|
215
|
-
file_hash: bundle.fileHash,
|
|
216
|
-
git_commit_hash: bundle.gitCommitHash,
|
|
217
|
-
message: bundle.message,
|
|
218
|
-
channel: bundle.channel,
|
|
219
|
-
storage_uri: bundle.storageUri,
|
|
220
|
-
target_app_version: bundle.targetAppVersion,
|
|
221
|
-
fingerprint_hash: bundle.fingerprintHash,
|
|
222
|
-
metadata: bundle.metadata ?? {}
|
|
223
|
-
};
|
|
224
|
-
const { id,...updateValues } = values;
|
|
225
|
-
await orm.upsert("bundles", {
|
|
226
|
-
where: (b) => b("id", "=", id),
|
|
227
|
-
create: values,
|
|
228
|
-
update: updateValues
|
|
229
|
-
});
|
|
230
|
-
},
|
|
231
|
-
async updateBundleById(bundleId, newBundle) {
|
|
232
|
-
const version = await client.version();
|
|
233
|
-
const orm = client.orm(version);
|
|
234
|
-
const current = await this.getBundleById(bundleId);
|
|
235
|
-
if (!current) throw new Error("targetBundleId not found");
|
|
236
|
-
const merged = {
|
|
237
|
-
...current,
|
|
238
|
-
...newBundle
|
|
239
|
-
};
|
|
240
|
-
const values = {
|
|
241
|
-
id: merged.id,
|
|
242
|
-
platform: merged.platform,
|
|
243
|
-
should_force_update: merged.shouldForceUpdate,
|
|
244
|
-
enabled: merged.enabled,
|
|
245
|
-
file_hash: merged.fileHash,
|
|
246
|
-
git_commit_hash: merged.gitCommitHash,
|
|
247
|
-
message: merged.message,
|
|
248
|
-
channel: merged.channel,
|
|
249
|
-
storage_uri: merged.storageUri,
|
|
250
|
-
target_app_version: merged.targetAppVersion,
|
|
251
|
-
fingerprint_hash: merged.fingerprintHash,
|
|
252
|
-
metadata: merged.metadata ?? {}
|
|
253
|
-
};
|
|
254
|
-
const { id: id2,...updateValues2 } = values;
|
|
255
|
-
await orm.upsert("bundles", {
|
|
256
|
-
where: (b) => b("id", "=", id2),
|
|
257
|
-
create: values,
|
|
258
|
-
update: updateValues2
|
|
259
|
-
});
|
|
260
|
-
},
|
|
261
|
-
async deleteBundleById(bundleId) {
|
|
262
|
-
const version = await client.version();
|
|
263
|
-
await client.orm(version).deleteMany("bundles", { where: (b) => b("id", "=", bundleId) });
|
|
264
|
-
}
|
|
265
|
-
},
|
|
266
|
-
adapterName: client.adapter.name,
|
|
267
|
-
createMigrator: () => client.createMigrator(),
|
|
268
|
-
generateSchema: client.generateSchema
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
//#endregion
|
|
273
|
-
export { HotUpdaterDB, createOrmDatabaseCore };
|
package/dist/db/pluginCore.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { getUpdateInfo } from "@hot-updater/js";
|
|
2
|
-
|
|
3
|
-
//#region src/db/pluginCore.ts
|
|
4
|
-
function createPluginDatabaseCore(plugin, resolveFileUrl) {
|
|
5
|
-
return {
|
|
6
|
-
api: {
|
|
7
|
-
async getBundleById(id) {
|
|
8
|
-
return plugin.getBundleById(id);
|
|
9
|
-
},
|
|
10
|
-
async getUpdateInfo(args) {
|
|
11
|
-
const where = {};
|
|
12
|
-
if ("platform" in args && args.platform) where.platform = args.platform;
|
|
13
|
-
where.channel = "channel" in args && args.channel ? args.channel : "production";
|
|
14
|
-
const { pagination } = await plugin.getBundles({
|
|
15
|
-
where,
|
|
16
|
-
limit: 1,
|
|
17
|
-
offset: 0
|
|
18
|
-
});
|
|
19
|
-
if (pagination.total === 0) return getUpdateInfo([], args);
|
|
20
|
-
const { data } = await plugin.getBundles({
|
|
21
|
-
where,
|
|
22
|
-
limit: pagination.total,
|
|
23
|
-
offset: 0
|
|
24
|
-
});
|
|
25
|
-
return getUpdateInfo(data, args);
|
|
26
|
-
},
|
|
27
|
-
async getAppUpdateInfo(args) {
|
|
28
|
-
const info = await this.getUpdateInfo(args);
|
|
29
|
-
if (!info) return null;
|
|
30
|
-
const { storageUri,...rest } = info;
|
|
31
|
-
const fileUrl = await resolveFileUrl(storageUri ?? null);
|
|
32
|
-
return {
|
|
33
|
-
...rest,
|
|
34
|
-
fileUrl
|
|
35
|
-
};
|
|
36
|
-
},
|
|
37
|
-
async getChannels() {
|
|
38
|
-
return plugin.getChannels();
|
|
39
|
-
},
|
|
40
|
-
async getBundles(options) {
|
|
41
|
-
return plugin.getBundles(options);
|
|
42
|
-
},
|
|
43
|
-
async insertBundle(bundle) {
|
|
44
|
-
await plugin.appendBundle(bundle);
|
|
45
|
-
await plugin.commitBundle();
|
|
46
|
-
},
|
|
47
|
-
async updateBundleById(bundleId, newBundle) {
|
|
48
|
-
await plugin.updateBundle(bundleId, newBundle);
|
|
49
|
-
await plugin.commitBundle();
|
|
50
|
-
},
|
|
51
|
-
async deleteBundleById(bundleId) {
|
|
52
|
-
const bundle = await plugin.getBundleById(bundleId);
|
|
53
|
-
if (!bundle) return;
|
|
54
|
-
await plugin.deleteBundle(bundle);
|
|
55
|
-
await plugin.commitBundle();
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
adapterName: plugin.name,
|
|
59
|
-
createMigrator: () => {
|
|
60
|
-
throw new Error("createMigrator is only available for Kysely/Prisma/Drizzle database adapters.");
|
|
61
|
-
},
|
|
62
|
-
generateSchema: () => {
|
|
63
|
-
throw new Error("generateSchema is only available for Kysely/Prisma/Drizzle database adapters.");
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
//#endregion
|
|
69
|
-
export { createPluginDatabaseCore };
|
package/dist/db/types.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { PaginationInfo } from "../types/index.js";
|
|
2
|
-
import { AppUpdateInfo, Bundle, GetBundlesArgs, UpdateInfo } from "@hot-updater/core";
|
|
3
|
-
import { DatabasePlugin, StoragePlugin } from "@hot-updater/plugin-core";
|
|
4
|
-
import { FumaDBAdapter } from "fumadb/adapters";
|
|
5
|
-
|
|
6
|
-
//#region src/db/types.d.ts
|
|
7
|
-
type DatabasePluginFactory = () => DatabasePlugin;
|
|
8
|
-
type DatabaseAdapter = FumaDBAdapter | DatabasePlugin | DatabasePluginFactory;
|
|
9
|
-
interface DatabaseAPI {
|
|
10
|
-
getBundleById(id: string): Promise<Bundle | null>;
|
|
11
|
-
getUpdateInfo(args: GetBundlesArgs): Promise<UpdateInfo | null>;
|
|
12
|
-
getAppUpdateInfo(args: GetBundlesArgs): Promise<AppUpdateInfo | null>;
|
|
13
|
-
getChannels(): Promise<string[]>;
|
|
14
|
-
getBundles(options: {
|
|
15
|
-
where?: {
|
|
16
|
-
channel?: string;
|
|
17
|
-
platform?: string;
|
|
18
|
-
};
|
|
19
|
-
limit: number;
|
|
20
|
-
offset: number;
|
|
21
|
-
}): Promise<{
|
|
22
|
-
data: Bundle[];
|
|
23
|
-
pagination: PaginationInfo;
|
|
24
|
-
}>;
|
|
25
|
-
insertBundle(bundle: Bundle): Promise<void>;
|
|
26
|
-
updateBundleById(bundleId: string, newBundle: Partial<Bundle>): Promise<void>;
|
|
27
|
-
deleteBundleById(bundleId: string): Promise<void>;
|
|
28
|
-
}
|
|
29
|
-
type StoragePluginFactory = () => StoragePlugin;
|
|
30
|
-
//#endregion
|
|
31
|
-
export { DatabaseAPI, DatabaseAdapter, StoragePluginFactory };
|
package/dist/handler.d.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { PaginationInfo } from "./types/index.js";
|
|
2
|
-
import { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, FingerprintGetBundlesArgs } from "@hot-updater/core";
|
|
3
|
-
|
|
4
|
-
//#region src/handler.d.ts
|
|
5
|
-
interface HandlerAPI {
|
|
6
|
-
getAppUpdateInfo: (args: AppVersionGetBundlesArgs | FingerprintGetBundlesArgs) => Promise<AppUpdateInfo | null>;
|
|
7
|
-
getBundleById: (id: string) => Promise<Bundle | null>;
|
|
8
|
-
getBundles: (options: {
|
|
9
|
-
where?: {
|
|
10
|
-
channel?: string;
|
|
11
|
-
platform?: string;
|
|
12
|
-
};
|
|
13
|
-
limit: number;
|
|
14
|
-
offset: number;
|
|
15
|
-
}) => Promise<{
|
|
16
|
-
data: Bundle[];
|
|
17
|
-
pagination: PaginationInfo;
|
|
18
|
-
}>;
|
|
19
|
-
insertBundle: (bundle: Bundle) => Promise<void>;
|
|
20
|
-
deleteBundleById: (bundleId: string) => Promise<void>;
|
|
21
|
-
getChannels: () => Promise<string[]>;
|
|
22
|
-
}
|
|
23
|
-
interface HandlerOptions {
|
|
24
|
-
/**
|
|
25
|
-
* Base path for all routes
|
|
26
|
-
* @default "/api"
|
|
27
|
-
*/
|
|
28
|
-
basePath?: string;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Creates a Web Standard Request handler for Hot Updater API
|
|
32
|
-
* This handler is framework-agnostic and works with any framework
|
|
33
|
-
* that supports Web Standard Request/Response (Hono, Elysia, etc.)
|
|
34
|
-
*/
|
|
35
|
-
declare function createHandler(api: HandlerAPI, options?: HandlerOptions): (request: Request) => Promise<Response>;
|
|
36
|
-
//#endregion
|
|
37
|
-
export { HandlerAPI, HandlerOptions, createHandler };
|
package/dist/handler.js
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { addRoute, createRouter, findRoute } from "rou3";
|
|
2
|
-
|
|
3
|
-
//#region src/handler.ts
|
|
4
|
-
const handleVersion = async () => {
|
|
5
|
-
return new Response(JSON.stringify({ version: "0.27.1" }), {
|
|
6
|
-
status: 200,
|
|
7
|
-
headers: { "Content-Type": "application/json" }
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
const handleFingerprintUpdate = async (params, _request, api) => {
|
|
11
|
-
const updateInfo = await api.getAppUpdateInfo({
|
|
12
|
-
_updateStrategy: "fingerprint",
|
|
13
|
-
platform: params.platform,
|
|
14
|
-
fingerprintHash: params.fingerprintHash,
|
|
15
|
-
channel: params.channel,
|
|
16
|
-
minBundleId: params.minBundleId,
|
|
17
|
-
bundleId: params.bundleId
|
|
18
|
-
});
|
|
19
|
-
return new Response(JSON.stringify(updateInfo), {
|
|
20
|
-
status: 200,
|
|
21
|
-
headers: { "Content-Type": "application/json" }
|
|
22
|
-
});
|
|
23
|
-
};
|
|
24
|
-
const handleAppVersionUpdate = async (params, _request, api) => {
|
|
25
|
-
const updateInfo = await api.getAppUpdateInfo({
|
|
26
|
-
_updateStrategy: "appVersion",
|
|
27
|
-
platform: params.platform,
|
|
28
|
-
appVersion: params.appVersion,
|
|
29
|
-
channel: params.channel,
|
|
30
|
-
minBundleId: params.minBundleId,
|
|
31
|
-
bundleId: params.bundleId
|
|
32
|
-
});
|
|
33
|
-
return new Response(JSON.stringify(updateInfo), {
|
|
34
|
-
status: 200,
|
|
35
|
-
headers: { "Content-Type": "application/json" }
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
const handleGetBundle = async (params, _request, api) => {
|
|
39
|
-
const bundle = await api.getBundleById(params.id);
|
|
40
|
-
if (!bundle) return new Response(JSON.stringify({ error: "Bundle not found" }), {
|
|
41
|
-
status: 404,
|
|
42
|
-
headers: { "Content-Type": "application/json" }
|
|
43
|
-
});
|
|
44
|
-
return new Response(JSON.stringify(bundle), {
|
|
45
|
-
status: 200,
|
|
46
|
-
headers: { "Content-Type": "application/json" }
|
|
47
|
-
});
|
|
48
|
-
};
|
|
49
|
-
const handleGetBundles = async (_params, request, api) => {
|
|
50
|
-
const url = new URL(request.url);
|
|
51
|
-
const channel = url.searchParams.get("channel") ?? void 0;
|
|
52
|
-
const platform = url.searchParams.get("platform") ?? void 0;
|
|
53
|
-
const limit = Number(url.searchParams.get("limit")) || 50;
|
|
54
|
-
const offset = Number(url.searchParams.get("offset")) || 0;
|
|
55
|
-
const result = await api.getBundles({
|
|
56
|
-
where: {
|
|
57
|
-
...channel && { channel },
|
|
58
|
-
...platform && { platform }
|
|
59
|
-
},
|
|
60
|
-
limit,
|
|
61
|
-
offset
|
|
62
|
-
});
|
|
63
|
-
return new Response(JSON.stringify(result.data), {
|
|
64
|
-
status: 200,
|
|
65
|
-
headers: { "Content-Type": "application/json" }
|
|
66
|
-
});
|
|
67
|
-
};
|
|
68
|
-
const handleCreateBundles = async (_params, request, api) => {
|
|
69
|
-
const body = await request.json();
|
|
70
|
-
const bundles = Array.isArray(body) ? body : [body];
|
|
71
|
-
for (const bundle of bundles) await api.insertBundle(bundle);
|
|
72
|
-
return new Response(JSON.stringify({ success: true }), {
|
|
73
|
-
status: 201,
|
|
74
|
-
headers: { "Content-Type": "application/json" }
|
|
75
|
-
});
|
|
76
|
-
};
|
|
77
|
-
const handleDeleteBundle = async (params, _request, api) => {
|
|
78
|
-
await api.deleteBundleById(params.id);
|
|
79
|
-
return new Response(JSON.stringify({ success: true }), {
|
|
80
|
-
status: 200,
|
|
81
|
-
headers: { "Content-Type": "application/json" }
|
|
82
|
-
});
|
|
83
|
-
};
|
|
84
|
-
const handleGetChannels = async (_params, _request, api) => {
|
|
85
|
-
const channels = await api.getChannels();
|
|
86
|
-
return new Response(JSON.stringify({ channels }), {
|
|
87
|
-
status: 200,
|
|
88
|
-
headers: { "Content-Type": "application/json" }
|
|
89
|
-
});
|
|
90
|
-
};
|
|
91
|
-
const routes = {
|
|
92
|
-
version: handleVersion,
|
|
93
|
-
fingerprintUpdate: handleFingerprintUpdate,
|
|
94
|
-
appVersionUpdate: handleAppVersionUpdate,
|
|
95
|
-
getBundle: handleGetBundle,
|
|
96
|
-
getBundles: handleGetBundles,
|
|
97
|
-
createBundles: handleCreateBundles,
|
|
98
|
-
deleteBundle: handleDeleteBundle,
|
|
99
|
-
getChannels: handleGetChannels
|
|
100
|
-
};
|
|
101
|
-
/**
|
|
102
|
-
* Creates a Web Standard Request handler for Hot Updater API
|
|
103
|
-
* This handler is framework-agnostic and works with any framework
|
|
104
|
-
* that supports Web Standard Request/Response (Hono, Elysia, etc.)
|
|
105
|
-
*/
|
|
106
|
-
function createHandler(api, options = {}) {
|
|
107
|
-
const basePath = options.basePath ?? "/api";
|
|
108
|
-
const router = createRouter();
|
|
109
|
-
addRoute(router, "GET", "/version", "version");
|
|
110
|
-
addRoute(router, "GET", "/fingerprint/:platform/:fingerprintHash/:channel/:minBundleId/:bundleId", "fingerprintUpdate");
|
|
111
|
-
addRoute(router, "GET", "/app-version/:platform/:appVersion/:channel/:minBundleId/:bundleId", "appVersionUpdate");
|
|
112
|
-
addRoute(router, "GET", "/api/bundles/channels", "getChannels");
|
|
113
|
-
addRoute(router, "GET", "/api/bundles/:id", "getBundle");
|
|
114
|
-
addRoute(router, "GET", "/api/bundles", "getBundles");
|
|
115
|
-
addRoute(router, "POST", "/api/bundles", "createBundles");
|
|
116
|
-
addRoute(router, "DELETE", "/api/bundles/:id", "deleteBundle");
|
|
117
|
-
return async (request) => {
|
|
118
|
-
try {
|
|
119
|
-
const path = new URL(request.url).pathname;
|
|
120
|
-
const method = request.method;
|
|
121
|
-
const match = findRoute(router, method, path.startsWith(basePath) ? path.slice(basePath.length) : path);
|
|
122
|
-
if (!match) return new Response(JSON.stringify({ error: "Not found" }), {
|
|
123
|
-
status: 404,
|
|
124
|
-
headers: { "Content-Type": "application/json" }
|
|
125
|
-
});
|
|
126
|
-
const handler = routes[match.data];
|
|
127
|
-
if (!handler) return new Response(JSON.stringify({ error: "Handler not found" }), {
|
|
128
|
-
status: 500,
|
|
129
|
-
headers: { "Content-Type": "application/json" }
|
|
130
|
-
});
|
|
131
|
-
return await handler(match.params || {}, request, api);
|
|
132
|
-
} catch (error) {
|
|
133
|
-
console.error("Hot Updater handler error:", error);
|
|
134
|
-
return new Response(JSON.stringify({
|
|
135
|
-
error: "Internal server error",
|
|
136
|
-
message: error instanceof Error ? error.message : "Unknown error"
|
|
137
|
-
}), {
|
|
138
|
-
status: 500,
|
|
139
|
-
headers: { "Content-Type": "application/json" }
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
//#endregion
|
|
146
|
-
export { createHandler };
|
package/dist/index.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { Bundle, PaginatedResult, PaginationInfo, PaginationOptions } from "./types/index.js";
|
|
2
|
-
import { HotUpdaterClient, HotUpdaterDB, Migrator } from "./db/ormCore.js";
|
|
3
|
-
import { HotUpdaterAPI, createHotUpdater } from "./db/index.js";
|
|
4
|
-
import { HandlerAPI, HandlerOptions, createHandler } from "./handler.js";
|
|
5
|
-
export { Bundle, HandlerAPI, HandlerOptions, HotUpdaterAPI, HotUpdaterClient, HotUpdaterDB, Migrator, PaginatedResult, PaginationInfo, PaginationOptions, createHandler, createHotUpdater };
|
package/dist/index.js
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|