@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
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import type { Bundle } from "@hot-updater/core";
|
|
2
|
+
import { NIL_UUID } from "@hot-updater/core";
|
|
3
|
+
import type {
|
|
4
|
+
DatabasePlugin,
|
|
5
|
+
RequestEnvContext,
|
|
6
|
+
StoragePlugin,
|
|
7
|
+
} from "@hot-updater/plugin-core";
|
|
8
|
+
import { describe, expect, expectTypeOf, it, vi } from "vitest";
|
|
9
|
+
import { createHotUpdater } from "./runtime";
|
|
10
|
+
|
|
11
|
+
const bundle: Bundle = {
|
|
12
|
+
id: "00000000-0000-0000-0000-000000000001",
|
|
13
|
+
platform: "ios",
|
|
14
|
+
shouldForceUpdate: false,
|
|
15
|
+
enabled: true,
|
|
16
|
+
fileHash: "hash123",
|
|
17
|
+
gitCommitHash: null,
|
|
18
|
+
message: "Test bundle",
|
|
19
|
+
channel: "production",
|
|
20
|
+
storageUri: "s3://test-bucket/bundles/bundle.zip",
|
|
21
|
+
targetAppVersion: "1.0.0",
|
|
22
|
+
fingerprintHash: null,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
type TestEnv = {
|
|
26
|
+
assetHost: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type TestContext = RequestEnvContext<TestEnv>;
|
|
30
|
+
|
|
31
|
+
describe("runtime createHotUpdater", () => {
|
|
32
|
+
it("passes the handler context to database and storage resolution", async () => {
|
|
33
|
+
const request = new Request(
|
|
34
|
+
"https://updates.example.com/api/check-update/app-version/ios/1.0.0/production/" +
|
|
35
|
+
`${NIL_UUID}/${NIL_UUID}`,
|
|
36
|
+
);
|
|
37
|
+
const getBundles = vi.fn<DatabasePlugin<TestContext>["getBundles"]>(
|
|
38
|
+
async () => {
|
|
39
|
+
return {
|
|
40
|
+
data: [bundle],
|
|
41
|
+
pagination: {
|
|
42
|
+
hasNextPage: false,
|
|
43
|
+
hasPreviousPage: false,
|
|
44
|
+
currentPage: 1,
|
|
45
|
+
totalPages: 1,
|
|
46
|
+
total: 1,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
const getDownloadUrl = vi.fn<StoragePlugin<TestContext>["getDownloadUrl"]>(
|
|
52
|
+
async (_storageUri, context) => {
|
|
53
|
+
return {
|
|
54
|
+
fileUrl: new URL("/bundle.zip", context?.env?.assetHost).toString(),
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const database: DatabasePlugin<TestContext> = {
|
|
60
|
+
name: "testDatabase",
|
|
61
|
+
async appendBundle() {},
|
|
62
|
+
async commitBundle() {},
|
|
63
|
+
async deleteBundle() {},
|
|
64
|
+
async getBundleById(id) {
|
|
65
|
+
return id === bundle.id ? bundle : null;
|
|
66
|
+
},
|
|
67
|
+
getBundles,
|
|
68
|
+
async getChannels() {
|
|
69
|
+
return ["production"];
|
|
70
|
+
},
|
|
71
|
+
async onUnmount() {},
|
|
72
|
+
async updateBundle() {},
|
|
73
|
+
};
|
|
74
|
+
const storage: StoragePlugin<TestContext> = {
|
|
75
|
+
name: "testStorage",
|
|
76
|
+
supportedProtocol: "s3",
|
|
77
|
+
async upload(key) {
|
|
78
|
+
return { storageUri: `s3://test-bucket/${key}` };
|
|
79
|
+
},
|
|
80
|
+
async delete() {},
|
|
81
|
+
getDownloadUrl,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const hotUpdater = createHotUpdater({
|
|
85
|
+
database,
|
|
86
|
+
storages: [storage],
|
|
87
|
+
basePath: "/api/check-update",
|
|
88
|
+
routes: {
|
|
89
|
+
updateCheck: true,
|
|
90
|
+
bundles: false,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
expectTypeOf(hotUpdater.handler)
|
|
95
|
+
.parameter(1)
|
|
96
|
+
.toEqualTypeOf<TestContext | undefined>();
|
|
97
|
+
|
|
98
|
+
const response = await hotUpdater.handler(request, {
|
|
99
|
+
env: {
|
|
100
|
+
assetHost: "https://assets.example.com",
|
|
101
|
+
},
|
|
102
|
+
request,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
expect(response.status).toBe(200);
|
|
106
|
+
await expect(response.json()).resolves.toEqual({
|
|
107
|
+
fileHash: "hash123",
|
|
108
|
+
fileUrl: "https://assets.example.com/bundle.zip",
|
|
109
|
+
id: "00000000-0000-0000-0000-000000000001",
|
|
110
|
+
message: "Test bundle",
|
|
111
|
+
shouldForceUpdate: false,
|
|
112
|
+
status: "UPDATE",
|
|
113
|
+
});
|
|
114
|
+
expect(getBundles).toHaveBeenCalledWith(
|
|
115
|
+
expect.any(Object),
|
|
116
|
+
expect.objectContaining({
|
|
117
|
+
env: {
|
|
118
|
+
assetHost: "https://assets.example.com",
|
|
119
|
+
},
|
|
120
|
+
request: expect.any(Request),
|
|
121
|
+
}),
|
|
122
|
+
);
|
|
123
|
+
expect(getDownloadUrl).toHaveBeenCalledWith(
|
|
124
|
+
"s3://test-bucket/bundles/bundle.zip",
|
|
125
|
+
expect.objectContaining({
|
|
126
|
+
env: {
|
|
127
|
+
assetHost: "https://assets.example.com",
|
|
128
|
+
},
|
|
129
|
+
request: expect.any(Request),
|
|
130
|
+
}),
|
|
131
|
+
);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("does not inject the request into context unless explicitly provided", async () => {
|
|
135
|
+
const getBundles = vi.fn<DatabasePlugin<TestContext>["getBundles"]>(
|
|
136
|
+
async () => {
|
|
137
|
+
return {
|
|
138
|
+
data: [bundle],
|
|
139
|
+
pagination: {
|
|
140
|
+
hasNextPage: false,
|
|
141
|
+
hasPreviousPage: false,
|
|
142
|
+
currentPage: 1,
|
|
143
|
+
totalPages: 1,
|
|
144
|
+
total: 1,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const database: DatabasePlugin<TestContext> = {
|
|
151
|
+
name: "testDatabase",
|
|
152
|
+
async appendBundle() {},
|
|
153
|
+
async commitBundle() {},
|
|
154
|
+
async deleteBundle() {},
|
|
155
|
+
async getBundleById(id) {
|
|
156
|
+
return id === bundle.id ? bundle : null;
|
|
157
|
+
},
|
|
158
|
+
getBundles,
|
|
159
|
+
async getChannels() {
|
|
160
|
+
return ["production"];
|
|
161
|
+
},
|
|
162
|
+
async onUnmount() {},
|
|
163
|
+
async updateBundle() {},
|
|
164
|
+
};
|
|
165
|
+
const storage: StoragePlugin<TestContext> = {
|
|
166
|
+
name: "testStorage",
|
|
167
|
+
supportedProtocol: "s3",
|
|
168
|
+
async upload(key) {
|
|
169
|
+
return { storageUri: `s3://test-bucket/${key}` };
|
|
170
|
+
},
|
|
171
|
+
async delete() {},
|
|
172
|
+
async getDownloadUrl() {
|
|
173
|
+
return { fileUrl: "https://assets.example.com/bundle.zip" };
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const hotUpdater = createHotUpdater({
|
|
178
|
+
database,
|
|
179
|
+
storages: [storage],
|
|
180
|
+
basePath: "/api/check-update",
|
|
181
|
+
routes: {
|
|
182
|
+
updateCheck: true,
|
|
183
|
+
bundles: false,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
const response = await hotUpdater.handler(
|
|
188
|
+
new Request(
|
|
189
|
+
"https://updates.example.com/api/check-update/app-version/ios/1.0.0/production/" +
|
|
190
|
+
`${NIL_UUID}/${NIL_UUID}`,
|
|
191
|
+
),
|
|
192
|
+
{
|
|
193
|
+
env: {
|
|
194
|
+
assetHost: "https://assets.example.com",
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
expect(response.status).toBe(200);
|
|
200
|
+
expect(getBundles).toHaveBeenCalledWith(expect.any(Object), {
|
|
201
|
+
env: {
|
|
202
|
+
assetHost: "https://assets.example.com",
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("supports stripped base-path requests and ignores extra framework args", async () => {
|
|
208
|
+
const getBundles = vi.fn<DatabasePlugin<TestContext>["getBundles"]>(
|
|
209
|
+
async () => {
|
|
210
|
+
return {
|
|
211
|
+
data: [bundle],
|
|
212
|
+
pagination: {
|
|
213
|
+
hasNextPage: false,
|
|
214
|
+
hasPreviousPage: false,
|
|
215
|
+
currentPage: 1,
|
|
216
|
+
totalPages: 1,
|
|
217
|
+
total: 1,
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
},
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
const database: DatabasePlugin<TestContext> = {
|
|
224
|
+
name: "testDatabase",
|
|
225
|
+
async appendBundle() {},
|
|
226
|
+
async commitBundle() {},
|
|
227
|
+
async deleteBundle() {},
|
|
228
|
+
async getBundleById(id) {
|
|
229
|
+
return id === bundle.id ? bundle : null;
|
|
230
|
+
},
|
|
231
|
+
getBundles,
|
|
232
|
+
async getChannels() {
|
|
233
|
+
return ["production"];
|
|
234
|
+
},
|
|
235
|
+
async onUnmount() {},
|
|
236
|
+
async updateBundle() {},
|
|
237
|
+
};
|
|
238
|
+
const storage: StoragePlugin<TestContext> = {
|
|
239
|
+
name: "testStorage",
|
|
240
|
+
supportedProtocol: "s3",
|
|
241
|
+
async upload(key) {
|
|
242
|
+
return { storageUri: `s3://test-bucket/${key}` };
|
|
243
|
+
},
|
|
244
|
+
async delete() {},
|
|
245
|
+
async getDownloadUrl() {
|
|
246
|
+
return { fileUrl: "https://assets.example.com/bundle.zip" };
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const hotUpdater = createHotUpdater({
|
|
251
|
+
database,
|
|
252
|
+
storages: [storage],
|
|
253
|
+
basePath: "/api/check-update",
|
|
254
|
+
routes: {
|
|
255
|
+
updateCheck: true,
|
|
256
|
+
bundles: false,
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
const mountStyleHandler = hotUpdater.handler as (
|
|
261
|
+
request: Request,
|
|
262
|
+
context?: unknown,
|
|
263
|
+
executionCtx?: unknown,
|
|
264
|
+
) => Promise<Response>;
|
|
265
|
+
const response = await mountStyleHandler(
|
|
266
|
+
new Request(
|
|
267
|
+
"https://updates.example.com/app-version/ios/1.0.0/production/" +
|
|
268
|
+
`${NIL_UUID}/${NIL_UUID}`,
|
|
269
|
+
),
|
|
270
|
+
{ someBinding: "ignored" },
|
|
271
|
+
{ waitUntil: () => undefined },
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
expect(response.status).toBe(200);
|
|
275
|
+
expect(getBundles).toHaveBeenCalledWith(expect.any(Object), undefined);
|
|
276
|
+
});
|
|
277
|
+
});
|
package/src/runtime.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
HotUpdaterContext,
|
|
3
|
+
StoragePlugin,
|
|
4
|
+
} from "@hot-updater/plugin-core";
|
|
5
|
+
import { createPluginDatabaseCore } from "./db/pluginCore";
|
|
6
|
+
import {
|
|
7
|
+
type DatabaseAdapter,
|
|
8
|
+
type DatabaseAPI,
|
|
9
|
+
isDatabasePlugin,
|
|
10
|
+
isDatabasePluginFactory,
|
|
11
|
+
type StoragePluginFactory,
|
|
12
|
+
} from "./db/types";
|
|
13
|
+
import { createHandler, type HandlerRoutes } from "./handler";
|
|
14
|
+
import { normalizeBasePath } from "./route";
|
|
15
|
+
|
|
16
|
+
export type HotUpdaterAPI<TContext = unknown> = DatabaseAPI<TContext> & {
|
|
17
|
+
basePath: string;
|
|
18
|
+
handler: (
|
|
19
|
+
request: Request,
|
|
20
|
+
context?: HotUpdaterContext<TContext>,
|
|
21
|
+
) => Promise<Response>;
|
|
22
|
+
adapterName: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export interface CreateHotUpdaterOptions<TContext = unknown> {
|
|
26
|
+
database: DatabaseAdapter<TContext>;
|
|
27
|
+
storages?: (StoragePlugin<TContext> | StoragePluginFactory<TContext>)[];
|
|
28
|
+
storagePlugins?: (StoragePlugin<TContext> | StoragePluginFactory<TContext>)[];
|
|
29
|
+
basePath?: string;
|
|
30
|
+
cwd?: string;
|
|
31
|
+
routes?: HandlerRoutes;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createHotUpdater<TContext = unknown>(
|
|
35
|
+
options: CreateHotUpdaterOptions<TContext>,
|
|
36
|
+
): HotUpdaterAPI<TContext> {
|
|
37
|
+
const basePath = normalizeBasePath(options.basePath ?? "/api");
|
|
38
|
+
const storagePlugins = (options.storages ?? options.storagePlugins ?? []).map(
|
|
39
|
+
(plugin) => (typeof plugin === "function" ? plugin() : plugin),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const resolveStoragePluginUrl = async (
|
|
43
|
+
storageUri: string | null,
|
|
44
|
+
context?: HotUpdaterContext<TContext>,
|
|
45
|
+
): Promise<string | null> => {
|
|
46
|
+
if (!storageUri) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const url = new URL(storageUri);
|
|
51
|
+
const protocol = url.protocol.replace(":", "");
|
|
52
|
+
|
|
53
|
+
if (protocol === "http" || protocol === "https") {
|
|
54
|
+
return storageUri;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const plugin = storagePlugins.find(
|
|
58
|
+
(item) => item.supportedProtocol === protocol,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
if (!plugin) {
|
|
62
|
+
throw new Error(`No storage plugin for protocol: ${protocol}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { fileUrl } = await plugin.getDownloadUrl(storageUri, context);
|
|
66
|
+
if (!fileUrl) {
|
|
67
|
+
throw new Error("Storage plugin returned empty fileUrl");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return fileUrl;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
if (
|
|
74
|
+
!isDatabasePluginFactory(options.database) &&
|
|
75
|
+
!isDatabasePlugin(options.database)
|
|
76
|
+
) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
"@hot-updater/server/runtime only supports database plugins.",
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const plugin = isDatabasePluginFactory(options.database)
|
|
83
|
+
? options.database()
|
|
84
|
+
: options.database;
|
|
85
|
+
const core = createPluginDatabaseCore<TContext>(
|
|
86
|
+
plugin,
|
|
87
|
+
resolveStoragePluginUrl,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const api = {
|
|
91
|
+
...core.api,
|
|
92
|
+
handler: createHandler(core.api, {
|
|
93
|
+
basePath,
|
|
94
|
+
routes: options.routes,
|
|
95
|
+
}),
|
|
96
|
+
adapterName: core.adapterName,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Some framework adapters strip the mounted base path or pass extra
|
|
100
|
+
// bindings/execution context arguments. Ignore those extras here so the
|
|
101
|
+
// handler can still be mounted directly as a plain Request handler.
|
|
102
|
+
const handler: HotUpdaterAPI<TContext>["handler"] = (
|
|
103
|
+
request,
|
|
104
|
+
context,
|
|
105
|
+
...extraArgs: unknown[]
|
|
106
|
+
) => {
|
|
107
|
+
if (extraArgs.length > 0) {
|
|
108
|
+
return api.handler(request);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return api.handler(request, context);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
...api,
|
|
116
|
+
basePath,
|
|
117
|
+
handler,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export { createHandler };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { column, idColumn, schema, table } from "fumadb/schema";
|
|
2
|
+
|
|
3
|
+
export const v0_29_0 = schema({
|
|
4
|
+
version: "0.29.0",
|
|
5
|
+
tables: {
|
|
6
|
+
bundles: table("bundles", {
|
|
7
|
+
id: idColumn("id", "uuid"),
|
|
8
|
+
platform: column("platform", "string"),
|
|
9
|
+
should_force_update: column("should_force_update", "bool"),
|
|
10
|
+
enabled: column("enabled", "bool"),
|
|
11
|
+
file_hash: column("file_hash", "string"),
|
|
12
|
+
git_commit_hash: column("git_commit_hash", "string").nullable(),
|
|
13
|
+
message: column("message", "string").nullable(),
|
|
14
|
+
channel: column("channel", "string"),
|
|
15
|
+
storage_uri: column("storage_uri", "string"),
|
|
16
|
+
target_app_version: column("target_app_version", "string").nullable(),
|
|
17
|
+
fingerprint_hash: column("fingerprint_hash", "string").nullable(),
|
|
18
|
+
metadata: column("metadata", "json"),
|
|
19
|
+
rollout_cohort_count: column("rollout_cohort_count", "integer").defaultTo(
|
|
20
|
+
1000,
|
|
21
|
+
),
|
|
22
|
+
target_cohorts: column("target_cohorts", "json").nullable(),
|
|
23
|
+
}),
|
|
24
|
+
},
|
|
25
|
+
relations: {},
|
|
26
|
+
});
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
//#region rolldown:runtime
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
|
|
25
|
-
exports.__toESM = __toESM;
|
package/dist/adapters/drizzle.js
DELETED
package/dist/adapters/kysely.js
DELETED
package/dist/adapters/mongodb.js
DELETED
package/dist/adapters/prisma.js
DELETED
package/dist/db/index.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { DatabaseAPI, DatabaseAdapter, StoragePluginFactory } from "./types.js";
|
|
2
|
-
import { HotUpdaterClient, HotUpdaterDB, Migrator } from "./ormCore.js";
|
|
3
|
-
import { StoragePlugin } from "@hot-updater/plugin-core";
|
|
4
|
-
|
|
5
|
-
//#region src/db/index.d.ts
|
|
6
|
-
type HotUpdaterAPI = DatabaseAPI & {
|
|
7
|
-
handler: (request: Request) => Promise<Response>;
|
|
8
|
-
adapterName: string;
|
|
9
|
-
createMigrator: () => Migrator;
|
|
10
|
-
generateSchema: HotUpdaterClient["generateSchema"];
|
|
11
|
-
};
|
|
12
|
-
interface HotUpdaterOptions {
|
|
13
|
-
database: DatabaseAdapter;
|
|
14
|
-
/**
|
|
15
|
-
* Storage plugins for handling file uploads and downloads.
|
|
16
|
-
*/
|
|
17
|
-
storages?: (StoragePlugin | StoragePluginFactory)[];
|
|
18
|
-
/**
|
|
19
|
-
* @deprecated Use `storages` instead. This field will be removed in a future version.
|
|
20
|
-
*/
|
|
21
|
-
storagePlugins?: (StoragePlugin | StoragePluginFactory)[];
|
|
22
|
-
basePath?: string;
|
|
23
|
-
cwd?: string;
|
|
24
|
-
}
|
|
25
|
-
declare function createHotUpdater(options: HotUpdaterOptions): HotUpdaterAPI;
|
|
26
|
-
//#endregion
|
|
27
|
-
export { HotUpdaterAPI, createHotUpdater };
|
package/dist/db/index.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { createHandler } from "../handler.js";
|
|
2
|
-
import { HotUpdaterDB, createOrmDatabaseCore } from "./ormCore.js";
|
|
3
|
-
import { createPluginDatabaseCore } from "./pluginCore.js";
|
|
4
|
-
import { isDatabasePlugin, isDatabasePluginFactory } from "./types.js";
|
|
5
|
-
|
|
6
|
-
//#region src/db/index.ts
|
|
7
|
-
function createHotUpdater(options) {
|
|
8
|
-
const storagePlugins = (options?.storages ?? options?.storagePlugins ?? []).map((plugin) => typeof plugin === "function" ? plugin() : plugin);
|
|
9
|
-
const resolveFileUrl = async (storageUri) => {
|
|
10
|
-
if (!storageUri) return null;
|
|
11
|
-
const protocol = new URL(storageUri).protocol.replace(":", "");
|
|
12
|
-
if (protocol === "http" || protocol === "https") return storageUri;
|
|
13
|
-
const plugin = storagePlugins.find((p) => p.supportedProtocol === protocol);
|
|
14
|
-
if (!plugin) throw new Error(`No storage plugin for protocol: ${protocol}`);
|
|
15
|
-
const { fileUrl } = await plugin.getDownloadUrl(storageUri);
|
|
16
|
-
if (!fileUrl) throw new Error("Storage plugin returned empty fileUrl");
|
|
17
|
-
return fileUrl;
|
|
18
|
-
};
|
|
19
|
-
let core;
|
|
20
|
-
const database = options.database;
|
|
21
|
-
if (isDatabasePluginFactory(database) || isDatabasePlugin(database)) core = createPluginDatabaseCore(isDatabasePluginFactory(database) ? database() : database, resolveFileUrl);
|
|
22
|
-
else core = createOrmDatabaseCore({
|
|
23
|
-
database,
|
|
24
|
-
resolveFileUrl
|
|
25
|
-
});
|
|
26
|
-
return {
|
|
27
|
-
...core.api,
|
|
28
|
-
handler: createHandler(core.api, options?.basePath ? { basePath: options.basePath } : {}),
|
|
29
|
-
adapterName: core.adapterName,
|
|
30
|
-
createMigrator: core.createMigrator,
|
|
31
|
-
generateSchema: core.generateSchema
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
//#endregion
|
|
36
|
-
export { createHotUpdater };
|
package/dist/db/ormCore.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import * as fumadb0 from "fumadb";
|
|
2
|
-
import { InferFumaDB } from "fumadb";
|
|
3
|
-
import * as fumadb_schema0 from "fumadb/schema";
|
|
4
|
-
import { FumaDBAdapter } from "fumadb/adapters";
|
|
5
|
-
|
|
6
|
-
//#region src/db/ormCore.d.ts
|
|
7
|
-
declare const HotUpdaterDB: fumadb0.FumaDBFactory<fumadb_schema0.Schema<"0.21.0", {
|
|
8
|
-
bundles: fumadb_schema0.Table<{
|
|
9
|
-
id: fumadb_schema0.IdColumn<"uuid", string, string>;
|
|
10
|
-
platform: fumadb_schema0.Column<"string", string, string>;
|
|
11
|
-
should_force_update: fumadb_schema0.Column<"bool", boolean, boolean>;
|
|
12
|
-
enabled: fumadb_schema0.Column<"bool", boolean, boolean>;
|
|
13
|
-
file_hash: fumadb_schema0.Column<"string", string, string>;
|
|
14
|
-
git_commit_hash: fumadb_schema0.Column<"string", string | null, string | null>;
|
|
15
|
-
message: fumadb_schema0.Column<"string", string | null, string | null>;
|
|
16
|
-
channel: fumadb_schema0.Column<"string", string, string>;
|
|
17
|
-
storage_uri: fumadb_schema0.Column<"string", string, string>;
|
|
18
|
-
target_app_version: fumadb_schema0.Column<"string", string | null, string | null>;
|
|
19
|
-
fingerprint_hash: fumadb_schema0.Column<"string", string | null, string | null>;
|
|
20
|
-
metadata: fumadb_schema0.Column<"json", unknown, unknown>;
|
|
21
|
-
}, {}>;
|
|
22
|
-
}>[]>;
|
|
23
|
-
type HotUpdaterClient = InferFumaDB<typeof HotUpdaterDB>;
|
|
24
|
-
type Migrator = ReturnType<HotUpdaterClient["createMigrator"]>;
|
|
25
|
-
//#endregion
|
|
26
|
-
export { HotUpdaterClient, HotUpdaterDB, Migrator };
|