@hot-updater/server 0.21.5 → 0.21.7

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/node.cjs ADDED
@@ -0,0 +1,51 @@
1
+
2
+ //#region src/node.ts
3
+ /**
4
+ * Converts a Hot Updater handler to a Node.js-compatible middleware
5
+ * Works with Express, Connect, and other frameworks using Node.js req/res
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { toNodeHandler } from "@hot-updater/server/node";
10
+ * import express from "express";
11
+ *
12
+ * const app = express();
13
+ *
14
+ * // Mount middleware
15
+ * app.use(express.json());
16
+ *
17
+ * // Mount hot-updater handler
18
+ * app.all("/hot-updater/*", toNodeHandler(hotUpdater));
19
+ * ```
20
+ */
21
+ function toNodeHandler(hotUpdater) {
22
+ return async (req, res) => {
23
+ try {
24
+ const url = `${req.protocol || "http"}://${req.get?.("host") || "localhost"}${req.url || "/"}`;
25
+ const headers = new Headers();
26
+ for (const [key, value] of Object.entries(req.headers)) if (value) headers.set(key, Array.isArray(value) ? value.join(", ") : value);
27
+ let body;
28
+ if (req.method && req.method !== "GET" && req.method !== "HEAD" && req.body) body = JSON.stringify(req.body);
29
+ const webRequest = new globalThis.Request(url, {
30
+ method: req.method || "GET",
31
+ headers,
32
+ body
33
+ });
34
+ const response = await hotUpdater.handler(webRequest);
35
+ res.status(response.status);
36
+ response.headers.forEach((value, key) => {
37
+ res.setHeader(key, value);
38
+ });
39
+ const text = await response.text();
40
+ if (text) res.send(text);
41
+ else res.end();
42
+ } catch (error) {
43
+ console.error("Hot Updater handler error:", error);
44
+ res.status(500);
45
+ res.send("Internal Server Error");
46
+ }
47
+ };
48
+ }
49
+
50
+ //#endregion
51
+ exports.toNodeHandler = toNodeHandler;
@@ -0,0 +1,25 @@
1
+ import { HotUpdaterAPI } from "./db/index.cjs";
2
+
3
+ //#region src/node.d.ts
4
+
5
+ /**
6
+ * Converts a Hot Updater handler to a Node.js-compatible middleware
7
+ * Works with Express, Connect, and other frameworks using Node.js req/res
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { toNodeHandler } from "@hot-updater/server/node";
12
+ * import express from "express";
13
+ *
14
+ * const app = express();
15
+ *
16
+ * // Mount middleware
17
+ * app.use(express.json());
18
+ *
19
+ * // Mount hot-updater handler
20
+ * app.all("/hot-updater/*", toNodeHandler(hotUpdater));
21
+ * ```
22
+ */
23
+ declare function toNodeHandler(hotUpdater: HotUpdaterAPI): (req: any, res: any, next?: any) => Promise<void>;
24
+ //#endregion
25
+ export { toNodeHandler };
package/dist/node.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { HotUpdaterAPI } from "./db/index.js";
2
+
3
+ //#region src/node.d.ts
4
+
5
+ /**
6
+ * Converts a Hot Updater handler to a Node.js-compatible middleware
7
+ * Works with Express, Connect, and other frameworks using Node.js req/res
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { toNodeHandler } from "@hot-updater/server/node";
12
+ * import express from "express";
13
+ *
14
+ * const app = express();
15
+ *
16
+ * // Mount middleware
17
+ * app.use(express.json());
18
+ *
19
+ * // Mount hot-updater handler
20
+ * app.all("/hot-updater/*", toNodeHandler(hotUpdater));
21
+ * ```
22
+ */
23
+ declare function toNodeHandler(hotUpdater: HotUpdaterAPI): (req: any, res: any, next?: any) => Promise<void>;
24
+ //#endregion
25
+ export { toNodeHandler };
package/dist/node.js ADDED
@@ -0,0 +1,50 @@
1
+ //#region src/node.ts
2
+ /**
3
+ * Converts a Hot Updater handler to a Node.js-compatible middleware
4
+ * Works with Express, Connect, and other frameworks using Node.js req/res
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { toNodeHandler } from "@hot-updater/server/node";
9
+ * import express from "express";
10
+ *
11
+ * const app = express();
12
+ *
13
+ * // Mount middleware
14
+ * app.use(express.json());
15
+ *
16
+ * // Mount hot-updater handler
17
+ * app.all("/hot-updater/*", toNodeHandler(hotUpdater));
18
+ * ```
19
+ */
20
+ function toNodeHandler(hotUpdater) {
21
+ return async (req, res) => {
22
+ try {
23
+ const url = `${req.protocol || "http"}://${req.get?.("host") || "localhost"}${req.url || "/"}`;
24
+ const headers = new Headers();
25
+ for (const [key, value] of Object.entries(req.headers)) if (value) headers.set(key, Array.isArray(value) ? value.join(", ") : value);
26
+ let body;
27
+ if (req.method && req.method !== "GET" && req.method !== "HEAD" && req.body) body = JSON.stringify(req.body);
28
+ const webRequest = new globalThis.Request(url, {
29
+ method: req.method || "GET",
30
+ headers,
31
+ body
32
+ });
33
+ const response = await hotUpdater.handler(webRequest);
34
+ res.status(response.status);
35
+ response.headers.forEach((value, key) => {
36
+ res.setHeader(key, value);
37
+ });
38
+ const text = await response.text();
39
+ if (text) res.send(text);
40
+ else res.end();
41
+ } catch (error) {
42
+ console.error("Hot Updater handler error:", error);
43
+ res.status(500);
44
+ res.send("Internal Server Error");
45
+ }
46
+ };
47
+ }
48
+
49
+ //#endregion
50
+ export { toNodeHandler };
@@ -2,11 +2,11 @@ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
2
  let fumadb_schema = require("fumadb/schema");
3
3
  fumadb_schema = require_rolldown_runtime.__toESM(fumadb_schema);
4
4
 
5
- //#region src/schema/v1.ts
6
- const v1 = (0, fumadb_schema.schema)({
7
- version: "1.0.0",
5
+ //#region src/schema/v0_21_0.ts
6
+ const v0_21_0 = (0, fumadb_schema.schema)({
7
+ version: "0.21.0",
8
8
  tables: { bundles: (0, fumadb_schema.table)("bundles", {
9
- id: (0, fumadb_schema.idColumn)("id", "varchar(255)").defaultTo$("auto"),
9
+ id: (0, fumadb_schema.idColumn)("id", "uuid"),
10
10
  platform: (0, fumadb_schema.column)("platform", "string"),
11
11
  should_force_update: (0, fumadb_schema.column)("should_force_update", "bool"),
12
12
  enabled: (0, fumadb_schema.column)("enabled", "bool"),
@@ -23,4 +23,4 @@ const v1 = (0, fumadb_schema.schema)({
23
23
  });
24
24
 
25
25
  //#endregion
26
- exports.v1 = v1;
26
+ exports.v0_21_0 = v0_21_0;
@@ -1,10 +1,10 @@
1
1
  import { column, idColumn, schema, table } from "fumadb/schema";
2
2
 
3
- //#region src/schema/v1.ts
4
- const v1 = schema({
5
- version: "1.0.0",
3
+ //#region src/schema/v0_21_0.ts
4
+ const v0_21_0 = schema({
5
+ version: "0.21.0",
6
6
  tables: { bundles: table("bundles", {
7
- id: idColumn("id", "varchar(255)").defaultTo$("auto"),
7
+ id: idColumn("id", "uuid"),
8
8
  platform: column("platform", "string"),
9
9
  should_force_update: column("should_force_update", "bool"),
10
10
  enabled: column("enabled", "bool"),
@@ -21,4 +21,4 @@ const v1 = schema({
21
21
  });
22
22
 
23
23
  //#endregion
24
- export { v1 };
24
+ export { v0_21_0 };
@@ -1,3 +1,4 @@
1
+ import { HotUpdaterAPI } from "../db/index.cjs";
1
2
  import { Bundle, Bundle as Bundle$1 } from "@hot-updater/core";
2
3
 
3
4
  //#region src/types/index.d.ts
@@ -1,3 +1,4 @@
1
+ import { HotUpdaterAPI } from "../db/index.js";
1
2
  import { Bundle, Bundle as Bundle$1 } from "@hot-updater/core";
2
3
 
3
4
  //#region src/types/index.d.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hot-updater/server",
3
- "version": "0.21.5",
3
+ "version": "0.21.7",
4
4
  "type": "module",
5
5
  "description": "React Native OTA solution for self-hosted",
6
6
  "sideEffects": false,
@@ -28,9 +28,9 @@
28
28
  "import": "./dist/adapters/prisma.js",
29
29
  "require": "./dist/adapters/prisma.cjs"
30
30
  },
31
- "./adapters/typeorm": {
32
- "import": "./dist/adapters/typeorm.js",
33
- "require": "./dist/adapters/typeorm.cjs"
31
+ "./node": {
32
+ "import": "./dist/node.js",
33
+ "require": "./dist/node.cjs"
34
34
  },
35
35
  "./package.json": "./package.json"
36
36
  },
@@ -46,10 +46,11 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "fumadb": "0.1.1",
49
+ "fumadb": "0.2.0",
50
+ "rou3": "0.7.9",
50
51
  "semver": "^7.7.2",
51
- "@hot-updater/core": "0.21.5",
52
- "@hot-updater/plugin-core": "0.21.5"
52
+ "@hot-updater/core": "0.21.7",
53
+ "@hot-updater/plugin-core": "0.21.7"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@electric-sql/pglite": "^0.2.17",
@@ -59,12 +60,13 @@
59
60
  "kysely": "^0.28.5",
60
61
  "kysely-pglite-dialect": "^1.2.0",
61
62
  "msw": "^2.7.0",
62
- "@hot-updater/aws": "0.21.5",
63
- "@hot-updater/firebase": "0.21.5",
64
- "@hot-updater/cloudflare": "0.21.5",
65
- "@hot-updater/standalone": "0.21.5",
66
- "@hot-updater/supabase": "0.21.5",
67
- "@hot-updater/test-utils": "0.21.5"
63
+ "uuidv7": "^1.0.2",
64
+ "@hot-updater/aws": "0.21.7",
65
+ "@hot-updater/cloudflare": "0.21.7",
66
+ "@hot-updater/firebase": "0.21.7",
67
+ "@hot-updater/standalone": "0.21.7",
68
+ "@hot-updater/test-utils": "0.21.7",
69
+ "@hot-updater/supabase": "0.21.7"
68
70
  },
69
71
  "scripts": {
70
72
  "build": "tsdown",
@@ -19,14 +19,14 @@ import {
19
19
  it,
20
20
  vi,
21
21
  } from "vitest";
22
- import { hotUpdater } from "./index";
22
+ import { createHotUpdater } from "./index";
23
23
 
24
24
  describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
25
25
  const db = new PGlite();
26
26
 
27
27
  const kysely = new Kysely({ dialect: new PGliteDialect(db) });
28
28
 
29
- const api = hotUpdater({
29
+ const hotUpdater = createHotUpdater({
30
30
  database: kyselyAdapter({
31
31
  db: kysely,
32
32
  provider: "postgresql",
@@ -58,7 +58,7 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
58
58
 
59
59
  beforeAll(async () => {
60
60
  // Initialize FumaDB schema to latest (creates tables under the hood)
61
- const migrator = api.createMigrator();
61
+ const migrator = hotUpdater.createMigrator();
62
62
  const result = await migrator.migrateToLatest({
63
63
  mode: "from-schema",
64
64
  updateSettings: true,
@@ -81,9 +81,9 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
81
81
  ): Promise<UpdateInfo | null> => {
82
82
  // Insert fixtures via the server API to exercise its types + mapping
83
83
  for (const b of bundles) {
84
- await api.insertBundle(b);
84
+ await hotUpdater.insertBundle(b);
85
85
  }
86
- return api.getUpdateInfo(options);
86
+ return hotUpdater.getUpdateInfo(options);
87
87
  };
88
88
 
89
89
  setupGetUpdateInfoTestSuite({ getUpdateInfo });
@@ -114,9 +114,9 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
114
114
  fingerprintHash: null,
115
115
  };
116
116
 
117
- await api.insertBundle(bundle);
117
+ await hotUpdater.insertBundle(bundle);
118
118
 
119
- const updateInfo = await api.getAppUpdateInfo({
119
+ const updateInfo = await hotUpdater.getAppUpdateInfo({
120
120
  appVersion: "1.0.0",
121
121
  bundleId: NIL_UUID,
122
122
  platform: "ios",
@@ -144,9 +144,9 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
144
144
  fingerprintHash: null,
145
145
  };
146
146
 
147
- await api.insertBundle(bundle);
147
+ await hotUpdater.insertBundle(bundle);
148
148
 
149
- const updateInfo = await api.getAppUpdateInfo({
149
+ const updateInfo = await hotUpdater.getAppUpdateInfo({
150
150
  appVersion: "1.0.0",
151
151
  bundleId: NIL_UUID,
152
152
  platform: "ios",
@@ -174,9 +174,9 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
174
174
  fingerprintHash: null,
175
175
  };
176
176
 
177
- await api.insertBundle(bundle);
177
+ await hotUpdater.insertBundle(bundle);
178
178
 
179
- const updateInfo = await api.getAppUpdateInfo({
179
+ const updateInfo = await hotUpdater.getAppUpdateInfo({
180
180
  appVersion: "1.0.0",
181
181
  bundleId: NIL_UUID,
182
182
  platform: "ios",
@@ -188,7 +188,7 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
188
188
  });
189
189
 
190
190
  it("returns null when no update is available", async () => {
191
- const updateInfo = await api.getAppUpdateInfo({
191
+ const updateInfo = await hotUpdater.getAppUpdateInfo({
192
192
  appVersion: "99.0.0",
193
193
  bundleId: NIL_UUID,
194
194
  platform: "ios",
@@ -213,9 +213,9 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
213
213
  fingerprintHash: "fingerprint123",
214
214
  };
215
215
 
216
- await api.insertBundle(bundle);
216
+ await hotUpdater.insertBundle(bundle);
217
217
 
218
- const updateInfo = await api.getAppUpdateInfo({
218
+ const updateInfo = await hotUpdater.getAppUpdateInfo({
219
219
  fingerprintHash: "fingerprint123",
220
220
  bundleId: NIL_UUID,
221
221
  platform: "ios",
package/src/db/index.ts CHANGED
@@ -14,12 +14,12 @@ import type { InferFumaDB } from "fumadb";
14
14
  import { fumadb } from "fumadb";
15
15
  import { calculatePagination } from "../calculatePagination";
16
16
  import { createHandler } from "../handler";
17
- import { v1 } from "../schema/v1";
17
+ import { v0_21_0 } from "../schema/v0_21_0";
18
18
  import type { PaginationInfo } from "../types";
19
19
 
20
20
  export const HotUpdaterDB = fumadb({
21
- namespace: "hot-updater",
22
- schemas: [v1],
21
+ namespace: "hot_updater",
22
+ schemas: [v0_21_0],
23
23
  });
24
24
 
25
25
  export type HotUpdaterClient = InferFumaDB<typeof HotUpdaterDB>;
@@ -43,9 +43,14 @@ export interface DatabaseAPI {
43
43
 
44
44
  export type HotUpdaterAPI = DatabaseAPI & {
45
45
  handler: (request: Request) => Promise<Response>;
46
- createMigrator: () => ReturnType<HotUpdaterClient["createMigrator"]>;
46
+
47
+ adapterName: string;
48
+ createMigrator: () => Migrator;
49
+ generateSchema: HotUpdaterClient["generateSchema"];
47
50
  };
48
51
 
52
+ export type Migrator = ReturnType<HotUpdaterClient["createMigrator"]>;
53
+
49
54
  export type StoragePluginFactory = (args: { cwd: string }) => StoragePlugin;
50
55
 
51
56
  export interface HotUpdaterOptions {
@@ -55,7 +60,7 @@ export interface HotUpdaterOptions {
55
60
  cwd?: string;
56
61
  }
57
62
 
58
- export function hotUpdater(options: HotUpdaterOptions): HotUpdaterAPI {
63
+ export function createHotUpdater(options: HotUpdaterOptions): HotUpdaterAPI {
59
64
  const client = HotUpdaterDB.client(options.database);
60
65
  const cwd = options.cwd ?? process.cwd();
61
66
 
@@ -485,6 +490,10 @@ export function hotUpdater(options: HotUpdaterOptions): HotUpdaterAPI {
485
490
  api,
486
491
  options?.basePath ? { basePath: options.basePath } : {},
487
492
  ),
493
+
494
+ // private method
495
+ adapterName: client.adapter.name,
488
496
  createMigrator: () => client.createMigrator(),
497
+ generateSchema: client.generateSchema,
489
498
  };
490
499
  }
@@ -7,8 +7,9 @@ import { Kysely } from "kysely";
7
7
  import { PGliteDialect } from "kysely-pglite-dialect";
8
8
  import { HttpResponse, http } from "msw";
9
9
  import { setupServer } from "msw/node";
10
+ import { uuidv7 } from "uuidv7";
10
11
  import { afterAll, afterEach, beforeAll, describe, expect, it } from "vitest";
11
- import { hotUpdater } from "./db";
12
+ import { createHotUpdater } from "./db";
12
13
 
13
14
  /**
14
15
  * Integration tests between @hot-updater/server handler and @hot-updater/standalone repository
@@ -25,7 +26,7 @@ const db = new PGlite();
25
26
  const kysely = new Kysely({ dialect: new PGliteDialect(db) });
26
27
 
27
28
  // Create handler API with in-memory DB
28
- const api = hotUpdater({
29
+ const api = createHotUpdater({
29
30
  database: kyselyAdapter({
30
31
  db: kysely,
31
32
  provider: "postgresql",
@@ -109,8 +110,9 @@ describe("Handler <-> Standalone Repository Integration", () => {
109
110
  baseUrl: `${baseUrl}/hot-updater`,
110
111
  })({ cwd: process.cwd() });
111
112
 
113
+ const bundleId = uuidv7();
112
114
  const bundle = createTestBundle({
113
- id: "integration-test-1",
115
+ id: bundleId,
114
116
  fileHash: "integration-hash-1",
115
117
  });
116
118
 
@@ -119,25 +121,23 @@ describe("Handler <-> Standalone Repository Integration", () => {
119
121
  await repo.commitBundle(); // Triggers actual commit
120
122
 
121
123
  // Verify via handler that bundle was created
122
- const request = new Request(
123
- `${baseUrl}/hot-updater/bundles/integration-test-1`,
124
- {
125
- method: "GET",
126
- },
127
- );
124
+ const request = new Request(`${baseUrl}/hot-updater/bundles/${bundleId}`, {
125
+ method: "GET",
126
+ });
128
127
 
129
128
  const response = await api.handler(request);
130
129
  expect(response.status).toBe(200);
131
130
 
132
131
  const retrieved = (await response.json()) as Bundle;
133
- expect(retrieved.id).toBe("integration-test-1");
132
+ expect(retrieved.id).toBe(bundleId);
134
133
  expect(retrieved.fileHash).toBe("integration-hash-1");
135
134
  });
136
135
 
137
136
  it("Real integration: getBundleById → handler GET /bundles/:id", async () => {
138
137
  // First, create a bundle directly via handler
138
+ const bundleId = uuidv7();
139
139
  const bundle = createTestBundle({
140
- id: "get-test-1",
140
+ id: bundleId,
141
141
  fileHash: "get-hash-1",
142
142
  });
143
143
 
@@ -149,24 +149,25 @@ describe("Handler <-> Standalone Repository Integration", () => {
149
149
  })({ cwd: process.cwd() });
150
150
 
151
151
  // Use standalone repository to retrieve
152
- const retrieved = await repo.getBundleById("get-test-1");
152
+ const retrieved = await repo.getBundleById(bundleId);
153
153
 
154
154
  expect(retrieved).toBeTruthy();
155
- expect(retrieved?.id).toBe("get-test-1");
155
+ expect(retrieved?.id).toBe(bundleId);
156
156
  expect(retrieved?.fileHash).toBe("get-hash-1");
157
157
  });
158
158
 
159
159
  it("Real integration: deleteBundle + commitBundle → handler DELETE /bundles/:id", async () => {
160
160
  // Create a bundle via handler
161
+ const bundleId = uuidv7();
161
162
  const bundle = createTestBundle({
162
- id: "delete-test-1",
163
+ id: bundleId,
163
164
  fileHash: "delete-hash-1",
164
165
  });
165
166
 
166
167
  await api.insertBundle(bundle);
167
168
 
168
169
  // Verify it exists
169
- const beforeDelete = await api.getBundleById("delete-test-1");
170
+ const beforeDelete = await api.getBundleById(bundleId);
170
171
  expect(beforeDelete).toBeTruthy();
171
172
 
172
173
  // Create standalone repository
@@ -179,20 +180,20 @@ describe("Handler <-> Standalone Repository Integration", () => {
179
180
  await repo.commitBundle();
180
181
 
181
182
  // Verify it was deleted
182
- const afterDelete = await api.getBundleById("delete-test-1");
183
+ const afterDelete = await api.getBundleById(bundleId);
183
184
  expect(afterDelete).toBeNull();
184
185
  });
185
186
 
186
187
  it("Real integration: getBundles → handler GET /bundles", async () => {
187
188
  // Create multiple bundles
188
189
  await api.insertBundle(
189
- createTestBundle({ id: "list-1", channel: "production" }),
190
+ createTestBundle({ id: uuidv7(), channel: "production" }),
190
191
  );
191
192
  await api.insertBundle(
192
- createTestBundle({ id: "list-2", channel: "production" }),
193
+ createTestBundle({ id: uuidv7(), channel: "production" }),
193
194
  );
194
195
  await api.insertBundle(
195
- createTestBundle({ id: "list-3", channel: "staging" }),
196
+ createTestBundle({ id: uuidv7(), channel: "staging" }),
196
197
  );
197
198
 
198
199
  // Create standalone repository
@@ -222,8 +223,9 @@ describe("Handler <-> Standalone Repository Integration", () => {
222
223
  })({ cwd: process.cwd() });
223
224
 
224
225
  // Step 1: Create bundle via standalone
226
+ const bundleId = uuidv7();
225
227
  const bundle = createTestBundle({
226
- id: "e2e-bundle",
228
+ id: bundleId,
227
229
  fileHash: "e2e-hash",
228
230
  enabled: true,
229
231
  });
@@ -232,16 +234,16 @@ describe("Handler <-> Standalone Repository Integration", () => {
232
234
  await repo.commitBundle();
233
235
 
234
236
  // Step 2: Retrieve via standalone
235
- const retrieved = await repo.getBundleById("e2e-bundle");
237
+ const retrieved = await repo.getBundleById(bundleId);
236
238
  expect(retrieved).toBeTruthy();
237
239
  expect(retrieved?.enabled).toBe(true);
238
240
 
239
241
  // Step 3: Update via standalone
240
- await repo.updateBundle("e2e-bundle", { enabled: false });
242
+ await repo.updateBundle(bundleId, { enabled: false });
241
243
  await repo.commitBundle();
242
244
 
243
245
  // Verify update
244
- const updated = await repo.getBundleById("e2e-bundle");
246
+ const updated = await repo.getBundleById(bundleId);
245
247
  expect(updated?.enabled).toBe(false);
246
248
 
247
249
  // Step 4: Delete via standalone
@@ -249,7 +251,7 @@ describe("Handler <-> Standalone Repository Integration", () => {
249
251
  await repo.commitBundle();
250
252
 
251
253
  // Verify deletion
252
- const deleted = await repo.getBundleById("e2e-bundle");
254
+ const deleted = await repo.getBundleById(bundleId);
253
255
  expect(deleted).toBeNull();
254
256
  });
255
257
 
@@ -259,17 +261,20 @@ describe("Handler <-> Standalone Repository Integration", () => {
259
261
  })({ cwd: process.cwd() });
260
262
 
261
263
  // Append multiple bundles
262
- await repo.appendBundle(createTestBundle({ id: "batch-1" }));
263
- await repo.appendBundle(createTestBundle({ id: "batch-2" }));
264
- await repo.appendBundle(createTestBundle({ id: "batch-3" }));
264
+ const bundleId1 = uuidv7();
265
+ const bundleId2 = uuidv7();
266
+ const bundleId3 = uuidv7();
267
+ await repo.appendBundle(createTestBundle({ id: bundleId1 }));
268
+ await repo.appendBundle(createTestBundle({ id: bundleId2 }));
269
+ await repo.appendBundle(createTestBundle({ id: bundleId3 }));
265
270
 
266
271
  // Commit all at once (standalone sends array in POST)
267
272
  await repo.commitBundle();
268
273
 
269
274
  // Verify all were created
270
- const bundle1 = await api.getBundleById("batch-1");
271
- const bundle2 = await api.getBundleById("batch-2");
272
- const bundle3 = await api.getBundleById("batch-3");
275
+ const bundle1 = await api.getBundleById(bundleId1);
276
+ const bundle2 = await api.getBundleById(bundleId2);
277
+ const bundle3 = await api.getBundleById(bundleId3);
273
278
 
274
279
  expect(bundle1).toBeTruthy();
275
280
  expect(bundle2).toBeTruthy();
@@ -278,7 +283,7 @@ describe("Handler <-> Standalone Repository Integration", () => {
278
283
 
279
284
  it("Works with custom basePath configuration", async () => {
280
285
  // Create handler with custom basePath
281
- const customApi = hotUpdater({
286
+ const customApi = createHotUpdater({
282
287
  database: kyselyAdapter({
283
288
  db: kysely,
284
289
  provider: "postgresql",
@@ -314,15 +319,16 @@ describe("Handler <-> Standalone Repository Integration", () => {
314
319
  })({ cwd: process.cwd() });
315
320
 
316
321
  // Test create and retrieve
322
+ const bundleId = uuidv7();
317
323
  const bundle = createTestBundle({
318
- id: "custom-path-test",
324
+ id: bundleId,
319
325
  fileHash: "custom-hash",
320
326
  });
321
327
 
322
328
  await repo.appendBundle(bundle);
323
329
  await repo.commitBundle();
324
330
 
325
- const retrieved = await repo.getBundleById("custom-path-test");
331
+ const retrieved = await repo.getBundleById(bundleId);
326
332
  expect(retrieved).toBeTruthy();
327
333
  expect(retrieved?.fileHash).toBe("custom-hash");
328
334
  });