@hot-updater/server 1.0.0-rc.0 → 1.0.0-rc.14

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.
Files changed (213) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +1 -1
  2. package/dist/adapters/databaseConstraintErrors.cjs +0 -1
  3. package/dist/adapters/databasePluginUtils.cjs +14 -1
  4. package/dist/adapters/databasePluginUtils.mjs +14 -2
  5. package/dist/adapters/drizzle.cjs +9 -4
  6. package/dist/adapters/drizzle.d.cts +0 -1
  7. package/dist/adapters/drizzle.d.mts +0 -1
  8. package/dist/adapters/drizzle.mjs +10 -4
  9. package/dist/adapters/drizzleCrud.cjs +93 -3
  10. package/dist/adapters/drizzleCrud.mjs +93 -5
  11. package/dist/adapters/drizzleLazyDB.cjs +2 -0
  12. package/dist/adapters/drizzleLazyDB.mjs +2 -0
  13. package/dist/adapters/drizzleQuery.cjs +3 -2
  14. package/dist/adapters/drizzleQuery.mjs +3 -1
  15. package/dist/adapters/kysely.cjs +1 -1
  16. package/dist/adapters/kysely.d.cts +0 -1
  17. package/dist/adapters/kysely.d.mts +0 -1
  18. package/dist/adapters/kysely.mjs +2 -1
  19. package/dist/adapters/kyselyCrud.cjs +44 -5
  20. package/dist/adapters/kyselyCrud.mjs +45 -6
  21. package/dist/adapters/kyselyQuery.cjs +2 -2
  22. package/dist/adapters/kyselyQuery.mjs +2 -1
  23. package/dist/adapters/mongodb.cjs +36 -1
  24. package/dist/adapters/mongodb.d.cts +1 -1
  25. package/dist/adapters/mongodb.d.mts +1 -1
  26. package/dist/adapters/mongodb.mjs +36 -0
  27. package/dist/adapters/mongodbCollections.cjs +2 -0
  28. package/dist/adapters/mongodbCollections.mjs +2 -0
  29. package/dist/adapters/mongodbQuery.cjs +17 -4
  30. package/dist/adapters/mongodbQuery.mjs +17 -4
  31. package/dist/adapters/mongodbReads.cjs +88 -30
  32. package/dist/adapters/mongodbReads.mjs +88 -29
  33. package/dist/adapters/mongodbWrites.cjs +1 -2
  34. package/dist/adapters/mongodbWrites.mjs +1 -1
  35. package/dist/adapters/prisma.cjs +44 -7
  36. package/dist/adapters/prisma.d.cts +0 -1
  37. package/dist/adapters/prisma.d.mts +0 -1
  38. package/dist/adapters/prisma.mjs +44 -6
  39. package/dist/adapters/prismaInsights.cjs +99 -0
  40. package/dist/adapters/prismaInsights.mjs +97 -0
  41. package/dist/adapters/prismaQuery.cjs +0 -1
  42. package/dist/adapters/prismaRows.cjs +7 -8
  43. package/dist/adapters/prismaRows.mjs +8 -8
  44. package/dist/apiKeys.cjs +6 -2
  45. package/dist/apiKeys.d.cts +0 -1
  46. package/dist/apiKeys.d.mts +0 -1
  47. package/dist/apiKeys.mjs +3 -3
  48. package/dist/createHotUpdaterCore.cjs +27 -12
  49. package/dist/createHotUpdaterCore.d.cts +8 -8
  50. package/dist/createHotUpdaterCore.d.mts +8 -8
  51. package/dist/createHotUpdaterCore.mjs +26 -12
  52. package/dist/db/createBundleDiff.cjs +2 -2
  53. package/dist/db/createBundleDiff.d.cts +1 -5
  54. package/dist/db/createBundleDiff.d.mts +1 -5
  55. package/dist/db/databasePluginCore.cjs +0 -1
  56. package/dist/db/fixedMigrator.cjs +2 -2
  57. package/dist/db/fixedMigrator.mjs +2 -2
  58. package/dist/db/fixedMigratorMongo.cjs +6 -4
  59. package/dist/db/fixedMigratorMongo.mjs +6 -4
  60. package/dist/db/index.d.cts +0 -1
  61. package/dist/db/index.d.mts +0 -1
  62. package/dist/db/releaseCatalog.cjs +0 -1
  63. package/dist/db/releaseCatalog.d.cts +0 -1
  64. package/dist/db/releaseCatalog.d.mts +0 -1
  65. package/dist/db/schema/insightsCollation.cjs +14 -0
  66. package/dist/db/schema/insightsCollation.mjs +14 -0
  67. package/dist/db/schema/sql.cjs +11 -7
  68. package/dist/db/schema/sql.mjs +8 -8
  69. package/dist/db/schemaGenerators.cjs +29 -9
  70. package/dist/db/schemaGenerators.mjs +29 -9
  71. package/dist/db/schemaReadiness.cjs +2 -0
  72. package/dist/db/schemaReadiness.d.cts +1 -0
  73. package/dist/db/schemaReadiness.d.mts +1 -0
  74. package/dist/db/schemaReadiness.mjs +2 -0
  75. package/dist/db/sqlMigrationExecution.cjs +1 -1
  76. package/dist/db/sqlMigrationExecution.mjs +1 -0
  77. package/dist/db/types.cjs +3 -1
  78. package/dist/db/types.d.cts +3 -6
  79. package/dist/db/types.d.mts +3 -6
  80. package/dist/db/types.mjs +2 -2
  81. package/dist/db/updateArtifacts.cjs +0 -1
  82. package/dist/handler.cjs +5 -5
  83. package/dist/handler.d.cts +1 -2
  84. package/dist/handler.d.mts +1 -2
  85. package/dist/handler.mjs +5 -5
  86. package/dist/handlerReleaseCatalogRoutes.cjs +0 -1
  87. package/dist/handlerReleaseManagementRoutes.cjs +0 -1
  88. package/dist/handlerTypes.d.cts +0 -1
  89. package/dist/handlerTypes.d.mts +0 -1
  90. package/dist/handlerVersionRoutes.d.cts +1 -0
  91. package/dist/handlerVersionRoutes.d.mts +1 -0
  92. package/dist/index.cjs +2 -2
  93. package/dist/index.d.cts +4 -4
  94. package/dist/index.d.mts +4 -4
  95. package/dist/index.mjs +2 -2
  96. package/dist/insights/domain.d.cts +92 -0
  97. package/dist/insights/domain.d.mts +92 -0
  98. package/dist/insights/errors.cjs +15 -0
  99. package/dist/insights/errors.mjs +14 -0
  100. package/dist/{analytics → insights}/eventInput.cjs +61 -16
  101. package/dist/{analytics → insights}/eventInput.mjs +61 -18
  102. package/dist/insights/provider.cjs +332 -0
  103. package/dist/insights/provider.d.cts +6 -0
  104. package/dist/insights/provider.d.mts +6 -0
  105. package/dist/insights/provider.mjs +332 -0
  106. package/dist/insights/queryInput.cjs +93 -0
  107. package/dist/insights/queryInput.mjs +91 -0
  108. package/dist/insights/routes.cjs +58 -0
  109. package/dist/insights/routes.mjs +56 -0
  110. package/dist/insights/types.d.cts +32 -0
  111. package/dist/insights/types.d.mts +32 -0
  112. package/dist/node.d.cts +0 -1
  113. package/dist/node.d.mts +0 -1
  114. package/dist/package.cjs +1 -1
  115. package/dist/package.mjs +1 -1
  116. package/dist/schema/index.cjs +17 -3
  117. package/dist/schema/index.mjs +4 -4
  118. package/dist/schema/v1_0_0.cjs +64 -35
  119. package/dist/schema/v1_0_0.mjs +64 -36
  120. package/dist/storageAccess.cjs +0 -1
  121. package/dist/types/index.d.cts +0 -1
  122. package/dist/types/index.d.mts +0 -1
  123. package/package.json +7 -7
  124. package/src/adapters/databasePluginTestDatabase.ts +15 -5
  125. package/src/adapters/databasePluginUtils.ts +24 -0
  126. package/src/adapters/drizzle.spec.ts +203 -5
  127. package/src/adapters/drizzle.ts +16 -4
  128. package/src/adapters/drizzleCrud.ts +200 -9
  129. package/src/adapters/drizzleLazyDB.ts +33 -6
  130. package/src/adapters/kysely.spec.ts +62 -0
  131. package/src/adapters/kysely.ts +7 -1
  132. package/src/adapters/kyselyCrud.ts +115 -7
  133. package/src/adapters/kyselyInsights.spec.ts +168 -0
  134. package/src/adapters/mongodb.integration.spec.ts +483 -0
  135. package/src/adapters/mongodb.spec.ts +89 -0
  136. package/src/adapters/mongodb.ts +59 -1
  137. package/src/adapters/mongodbCollections.ts +16 -0
  138. package/src/adapters/mongodbQuery.ts +22 -3
  139. package/src/adapters/mongodbReads.ts +78 -2
  140. package/src/adapters/mongodbTestClient.ts +107 -6
  141. package/src/adapters/mongodbTestFilter.ts +5 -1
  142. package/src/adapters/mongodbWrites.ts +1 -0
  143. package/src/adapters/prisma.spec.ts +270 -0
  144. package/src/adapters/prisma.ts +75 -2
  145. package/src/adapters/prismaInsights.ts +190 -0
  146. package/src/adapters/prismaRows.ts +17 -10
  147. package/src/adapters/prismaTestClient.ts +89 -7
  148. package/src/apiKeys.integration.spec.ts +3 -3
  149. package/src/createHotUpdaterCore.ts +30 -16
  150. package/src/db/databasePluginUpdateCheck.bench.ts +10 -0
  151. package/src/db/fixedMigrator.spec.ts +63 -0
  152. package/src/db/fixedMigratorMongo.spec.ts +70 -9
  153. package/src/db/fixedMigratorMongo.ts +10 -10
  154. package/src/db/index.spec.ts +6 -1
  155. package/src/db/schema/insightsCollation.ts +21 -0
  156. package/src/db/schema/sql.ts +8 -5
  157. package/src/db/schemaGenerators.ts +42 -13
  158. package/src/db/types.spec.ts +11 -3
  159. package/src/db/types.ts +13 -7
  160. package/src/handler-standalone.integration.spec.ts +6 -8
  161. package/src/handler.ts +12 -12
  162. package/src/index.ts +3 -3
  163. package/src/insights/domain.ts +106 -0
  164. package/src/insights/errors.ts +11 -0
  165. package/src/{analytics → insights}/eventInput.ts +66 -16
  166. package/src/insights/insights.integration.spec.ts +475 -0
  167. package/src/insights/provider.spec.ts +396 -0
  168. package/src/insights/provider.ts +611 -0
  169. package/src/insights/queryInput.ts +142 -0
  170. package/src/insights/routes.ts +104 -0
  171. package/src/insights/types.ts +55 -0
  172. package/src/schema/dsl-all-versions.spec.ts +1 -1
  173. package/src/schema/v1_0_0.spec.ts +77 -3
  174. package/src/schema/v1_0_0.ts +83 -37
  175. package/dist/analytics/bounded/activeOverview.cjs +0 -87
  176. package/dist/analytics/bounded/activeOverview.mjs +0 -85
  177. package/dist/analytics/bounded/installationSearch.cjs +0 -42
  178. package/dist/analytics/bounded/installationSearch.mjs +0 -42
  179. package/dist/analytics/bounded/persistence.cjs +0 -39
  180. package/dist/analytics/bounded/persistence.mjs +0 -38
  181. package/dist/analytics/bounded/provider.cjs +0 -170
  182. package/dist/analytics/bounded/provider.d.cts +0 -7
  183. package/dist/analytics/bounded/provider.d.mts +0 -7
  184. package/dist/analytics/bounded/provider.mjs +0 -170
  185. package/dist/analytics/bounded/scan.cjs +0 -144
  186. package/dist/analytics/bounded/scan.mjs +0 -138
  187. package/dist/analytics/domain.d.cts +0 -121
  188. package/dist/analytics/domain.d.mts +0 -121
  189. package/dist/analytics/errors.cjs +0 -22
  190. package/dist/analytics/errors.mjs +0 -20
  191. package/dist/analytics/persistence.d.cts +0 -6
  192. package/dist/analytics/persistence.d.mts +0 -6
  193. package/dist/analytics/queryInput.cjs +0 -58
  194. package/dist/analytics/queryInput.mjs +0 -55
  195. package/dist/analytics/routes.cjs +0 -63
  196. package/dist/analytics/routes.mjs +0 -61
  197. package/dist/analytics/types.d.cts +0 -17
  198. package/dist/analytics/types.d.mts +0 -17
  199. package/src/analytics/analytics.integration.spec.ts +0 -144
  200. package/src/analytics/bounded/activeOverview.spec.ts +0 -189
  201. package/src/analytics/bounded/activeOverview.ts +0 -148
  202. package/src/analytics/bounded/installationSearch.spec.ts +0 -130
  203. package/src/analytics/bounded/installationSearch.ts +0 -69
  204. package/src/analytics/bounded/persistence.ts +0 -43
  205. package/src/analytics/bounded/provider.spec.ts +0 -219
  206. package/src/analytics/bounded/provider.ts +0 -229
  207. package/src/analytics/bounded/scan.ts +0 -235
  208. package/src/analytics/domain.ts +0 -139
  209. package/src/analytics/errors.ts +0 -18
  210. package/src/analytics/persistence.ts +0 -10
  211. package/src/analytics/queryInput.ts +0 -102
  212. package/src/analytics/routes.ts +0 -123
  213. package/src/analytics/types.ts +0 -44
@@ -0,0 +1,32 @@
1
+ import { ActiveInstallationWindow, CreateBundleEventRequest, CursorPage, EventCursorPage, EventHistoryRow, InsightsBundleSelection, InsightsScope, InstallationHistoryRow, InstallationRow, ReportingOverview } from "./domain.mjs";
2
+ //#region src/insights/types.d.ts
3
+ type InsightsEventPageInput = {
4
+ readonly beforeReceivedAtMs?: number;
5
+ readonly sinceMs?: number;
6
+ readonly bundle?: InsightsBundleSelection;
7
+ readonly cursor?: string;
8
+ readonly limit?: number;
9
+ };
10
+ type InsightsInstallationEventPageInput = Omit<InsightsEventPageInput, "bundle"> & {
11
+ readonly installId: string;
12
+ };
13
+ type InsightsUserInstallationPageInput = {
14
+ readonly userId: string;
15
+ readonly cursor?: string;
16
+ readonly limit?: number;
17
+ };
18
+ type InsightsProvider = {
19
+ appendBundleEvent(input: CreateBundleEventRequest): Promise<void>;
20
+ listEvents(input: InsightsEventPageInput): Promise<EventCursorPage<EventHistoryRow>>;
21
+ listInstallationEvents(input: InsightsInstallationEventPageInput): Promise<EventCursorPage<InstallationHistoryRow>>;
22
+ getInstallation(input: {
23
+ readonly installId: string;
24
+ }): Promise<InstallationRow | null>;
25
+ pageInstallationsByCurrentUserId(input: InsightsUserInstallationPageInput): Promise<CursorPage<InstallationRow>>;
26
+ getReportingOverview(input: InsightsScope & {
27
+ readonly window: ActiveInstallationWindow;
28
+ readonly bundleId?: string;
29
+ }): Promise<ReportingOverview>;
30
+ };
31
+ //#endregion
32
+ export { InsightsEventPageInput, InsightsInstallationEventPageInput, InsightsProvider, InsightsUserInstallationPageInput };
package/dist/node.d.cts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { HotUpdaterHandler } from "./handlerTypes.cjs";
2
2
  import { HOT_UPDATER_SERVER_VERSION } from "./version.cjs";
3
3
  import { HOT_UPDATER_INFRASTRUCTURE_GENERATION } from "./handlerVersionRoutes.cjs";
4
-
5
4
  //#region src/node.d.ts
6
5
  /**
7
6
  * Converts a Hot Updater handler to a Node.js-compatible middleware
package/dist/node.d.mts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { HotUpdaterHandler } from "./handlerTypes.mjs";
2
2
  import { HOT_UPDATER_SERVER_VERSION } from "./version.mjs";
3
3
  import { HOT_UPDATER_INFRASTRUCTURE_GENERATION } from "./handlerVersionRoutes.mjs";
4
-
5
4
  //#region src/node.d.ts
6
5
  /**
7
6
  * Converts a Hot Updater handler to a Node.js-compatible middleware
package/dist/package.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "1.0.0-rc.0";
2
+ var version = "1.0.0-rc.14";
3
3
  //#endregion
4
4
  Object.defineProperty(exports, "version", {
5
5
  enumerable: true,
package/dist/package.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "1.0.0-rc.0";
2
+ var version = "1.0.0-rc.14";
3
3
  //#endregion
4
4
  export { version };
@@ -1,6 +1,20 @@
1
- require("./types.cjs");
2
- require("./settings.cjs");
1
+ const require_types = require("./types.cjs");
2
+ const require_settings = require("./settings.cjs");
3
+ const require_v1_0_0 = require("./v1_0_0.cjs");
3
4
  //#region src/schema/index.ts
4
- const hotUpdaterSchemaVersions = [require("./v1_0_0.cjs").v1_0_0];
5
+ const hotUpdaterSchemaVersions = [require_v1_0_0.v1_0_0];
5
6
  //#endregion
7
+ exports.HOT_UPDATER_CORE_SCHEMA_KEY = require_types.HOT_UPDATER_CORE_SCHEMA_KEY;
8
+ exports.HOT_UPDATER_SCHEMA_VERSION = require_types.HOT_UPDATER_SCHEMA_VERSION;
9
+ exports.HOT_UPDATER_SETTINGS_TABLE = require_types.HOT_UPDATER_SETTINGS_TABLE;
10
+ exports.apiKeysV100 = require_v1_0_0.apiKeysV100;
11
+ exports.bundleEventHeadsV100 = require_v1_0_0.bundleEventHeadsV100;
12
+ exports.bundleEventsV100 = require_v1_0_0.bundleEventsV100;
13
+ exports.bundlePatchesV100 = require_v1_0_0.bundlePatchesV100;
14
+ exports.bundlesV100 = require_v1_0_0.bundlesV100;
15
+ exports.channelsV100 = require_v1_0_0.channelsV100;
16
+ exports.createSettingsTable = require_settings.createSettingsTable;
6
17
  exports.hotUpdaterSchemaVersions = hotUpdaterSchemaVersions;
18
+ exports.releaseCatalogsV100 = require_v1_0_0.releaseCatalogsV100;
19
+ exports.releasesV100 = require_v1_0_0.releasesV100;
20
+ exports.v1_0_0 = require_v1_0_0.v1_0_0;
@@ -1,7 +1,7 @@
1
- import "./types.mjs";
2
- import "./settings.mjs";
3
- import { v1_0_0 } from "./v1_0_0.mjs";
1
+ import { HOT_UPDATER_CORE_SCHEMA_KEY, HOT_UPDATER_SCHEMA_VERSION, HOT_UPDATER_SETTINGS_TABLE } from "./types.mjs";
2
+ import { createSettingsTable } from "./settings.mjs";
3
+ import { apiKeysV100, bundleEventHeadsV100, bundleEventsV100, bundlePatchesV100, bundlesV100, channelsV100, releaseCatalogsV100, releasesV100, v1_0_0 } from "./v1_0_0.mjs";
4
4
  //#region src/schema/index.ts
5
5
  const hotUpdaterSchemaVersions = [v1_0_0];
6
6
  //#endregion
7
- export { hotUpdaterSchemaVersions };
7
+ export { HOT_UPDATER_CORE_SCHEMA_KEY, HOT_UPDATER_SCHEMA_VERSION, HOT_UPDATER_SETTINGS_TABLE, apiKeysV100, bundleEventHeadsV100, bundleEventsV100, bundlePatchesV100, bundlesV100, channelsV100, createSettingsTable, hotUpdaterSchemaVersions, releaseCatalogsV100, releasesV100, v1_0_0 };
@@ -255,71 +255,66 @@ const releaseCatalogsV100 = require_dsl.table("release_catalogs", {
255
255
  referencedColumns: ["id"]
256
256
  })]
257
257
  });
258
+ const insightsTextCollations = {
259
+ postgresql: "\"C\"",
260
+ mysql: "utf8mb4_0900_bin"
261
+ };
262
+ const insightsProviders = [
263
+ "postgresql",
264
+ "mysql",
265
+ "sqlite",
266
+ "cockroachdb",
267
+ "mongodb"
268
+ ];
258
269
  const bundleEventsV100 = require_dsl.table("bundle_events", {
259
270
  id: require_dsl.idColumn("id", "uuid"),
260
- type: require_dsl.stringColumn("type"),
261
- install_id: require_dsl.stringColumn("install_id"),
262
- user_id: require_dsl.stringColumn("user_id").nullable(),
263
- username: require_dsl.stringColumn("username").nullable(),
271
+ type: require_dsl.column("type", require_dsl.varchar(32)),
272
+ install_id: require_dsl.column("install_id", require_dsl.varchar(255)).collate(insightsTextCollations),
273
+ user_id: require_dsl.column("user_id", require_dsl.varchar(255)).collate(insightsTextCollations).nullable(),
264
274
  from_release_id: require_dsl.uuid("from_release_id").nullable(),
265
275
  from_bundle_id: require_dsl.uuid("from_bundle_id").nullable(),
266
276
  to_release_id: require_dsl.uuid("to_release_id").nullable(),
267
277
  to_bundle_id: require_dsl.uuid("to_bundle_id"),
268
- platform: require_dsl.stringColumn("platform"),
278
+ platform: require_dsl.stringColumn("platform").collate(insightsTextCollations),
269
279
  app_version: require_dsl.stringColumn("app_version"),
270
- channel: require_dsl.stringColumn("channel"),
271
- cohort: require_dsl.stringColumn("cohort"),
272
- update_strategy: require_dsl.stringColumn("update_strategy").nullable(),
273
- fingerprint_hash: require_dsl.stringColumn("fingerprint_hash").nullable(),
274
- sdk_version: require_dsl.stringColumn("sdk_version").nullable(),
280
+ channel: require_dsl.stringColumn("channel").collate(insightsTextCollations),
281
+ metadata: require_dsl.json("metadata"),
275
282
  received_at_ms: require_dsl.float("received_at_ms")
276
283
  }, {
277
284
  indexes: [
278
285
  require_dsl.index("bundle_events_received_at_idx", ["received_at_ms", "id"]),
279
- require_dsl.index("bundle_events_install_idx", [
286
+ require_dsl.index("bundle_events_latest_idx", [
280
287
  "install_id",
281
288
  "received_at_ms",
282
289
  "id"
283
290
  ]),
284
- require_dsl.index("bundle_events_user_id_idx", [
285
- "user_id",
286
- "received_at_ms",
287
- "id"
288
- ]),
289
- require_dsl.index("bundle_events_username_idx", [
290
- "username",
291
- "received_at_ms",
292
- "id"
293
- ]),
294
- require_dsl.index("bundle_events_to_bundle_idx", [
291
+ require_dsl.index("bundle_events_install_idx", [
292
+ "install_id",
295
293
  "type",
296
- "to_bundle_id",
297
294
  "received_at_ms",
298
295
  "id"
299
296
  ]),
300
297
  require_dsl.index("bundle_events_from_bundle_idx", [
301
298
  "type",
299
+ "platform",
300
+ "channel",
302
301
  "from_bundle_id",
303
302
  "received_at_ms",
304
303
  "id"
305
- ]),
306
- require_dsl.index("bundle_events_to_release_idx", [
307
- "type",
308
- "to_release_id",
309
- "received_at_ms",
310
- "id"
311
- ]),
312
- require_dsl.index("bundle_events_from_release_idx", [
304
+ ], insightsProviders),
305
+ require_dsl.index("bundle_events_to_bundle_idx", [
313
306
  "type",
314
- "from_release_id",
307
+ "platform",
308
+ "channel",
309
+ "to_bundle_id",
315
310
  "received_at_ms",
316
311
  "id"
317
- ])
312
+ ], insightsProviders)
318
313
  ],
319
314
  checks: [
320
315
  require_dsl.check({
321
316
  name: "bundle_events_type_check",
322
- expression: "type in ('UPDATE_APPLIED', 'RECOVERED', 'RELEASE_ADOPTED', 'UNCHANGED')",
317
+ expression: "type in ('UPDATE_DOWNLOADED', 'UPDATE_APPLIED', 'RECOVERED', 'UNCHANGED')",
323
318
  sqliteInline: true
324
319
  }),
325
320
  require_dsl.check({
@@ -329,7 +324,7 @@ const bundleEventsV100 = require_dsl.table("bundle_events", {
329
324
  }),
330
325
  require_dsl.check({
331
326
  name: "bundle_events_shape_check",
332
- expression: "((type in ('UPDATE_APPLIED', 'RECOVERED', 'RELEASE_ADOPTED')) and from_bundle_id is not null and update_strategy is not null and update_strategy in ('fingerprint', 'appVersion')) or (type = 'UNCHANGED' and from_bundle_id is null and update_strategy is null)",
327
+ expression: "((type in ('UPDATE_DOWNLOADED', 'UPDATE_APPLIED', 'RECOVERED')) and from_bundle_id is not null) or (type = 'UNCHANGED' and from_bundle_id is null)",
333
328
  sqliteInline: true
334
329
  }),
335
330
  require_dsl.check({
@@ -339,6 +334,38 @@ const bundleEventsV100 = require_dsl.table("bundle_events", {
339
334
  })
340
335
  ]
341
336
  });
337
+ const bundleEventHeadsV100 = require_dsl.table("bundle_event_heads", {
338
+ install_id: require_dsl.idColumn("install_id", require_dsl.varchar(255)).collate(insightsTextCollations),
339
+ id: require_dsl.uuid("id"),
340
+ received_at_ms: require_dsl.float("received_at_ms"),
341
+ user_id: require_dsl.column("user_id", require_dsl.varchar(255)).collate(insightsTextCollations).nullable(),
342
+ platform: require_dsl.stringColumn("platform").collate(insightsTextCollations),
343
+ channel: require_dsl.stringColumn("channel").collate(insightsTextCollations),
344
+ type: require_dsl.column("type", require_dsl.varchar(32)),
345
+ from_bundle_id: require_dsl.uuid("from_bundle_id").nullable(),
346
+ to_bundle_id: require_dsl.uuid("to_bundle_id")
347
+ }, { indexes: [
348
+ require_dsl.index("bundle_event_heads_user_idx", ["user_id", "install_id"]),
349
+ require_dsl.index("bundle_event_heads_scope_idx", [
350
+ "platform",
351
+ "channel",
352
+ "received_at_ms"
353
+ ], insightsProviders),
354
+ require_dsl.index("bundle_event_heads_from_idx", [
355
+ "type",
356
+ "platform",
357
+ "channel",
358
+ "from_bundle_id",
359
+ "received_at_ms"
360
+ ], insightsProviders),
361
+ require_dsl.index("bundle_event_heads_to_idx", [
362
+ "type",
363
+ "platform",
364
+ "channel",
365
+ "to_bundle_id",
366
+ "received_at_ms"
367
+ ], insightsProviders)
368
+ ] });
342
369
  const v1_0_0 = require_dsl.schema({
343
370
  version: "1.0.0",
344
371
  settingsTable: require_types.HOT_UPDATER_SETTINGS_TABLE,
@@ -349,12 +376,14 @@ const v1_0_0 = require_dsl.schema({
349
376
  releasesV100,
350
377
  releaseCatalogsV100,
351
378
  bundleEventsV100,
379
+ bundleEventHeadsV100,
352
380
  apiKeysV100,
353
381
  require_settings.createSettingsTable("1.0.0")
354
382
  ]
355
383
  });
356
384
  //#endregion
357
385
  exports.apiKeysV100 = apiKeysV100;
386
+ exports.bundleEventHeadsV100 = bundleEventHeadsV100;
358
387
  exports.bundleEventsV100 = bundleEventsV100;
359
388
  exports.bundlePatchesV100 = bundlePatchesV100;
360
389
  exports.bundlesV100 = bundlesV100;
@@ -255,71 +255,66 @@ const releaseCatalogsV100 = table("release_catalogs", {
255
255
  referencedColumns: ["id"]
256
256
  })]
257
257
  });
258
+ const insightsTextCollations = {
259
+ postgresql: "\"C\"",
260
+ mysql: "utf8mb4_0900_bin"
261
+ };
262
+ const insightsProviders = [
263
+ "postgresql",
264
+ "mysql",
265
+ "sqlite",
266
+ "cockroachdb",
267
+ "mongodb"
268
+ ];
258
269
  const bundleEventsV100 = table("bundle_events", {
259
270
  id: idColumn("id", "uuid"),
260
- type: stringColumn("type"),
261
- install_id: stringColumn("install_id"),
262
- user_id: stringColumn("user_id").nullable(),
263
- username: stringColumn("username").nullable(),
271
+ type: column("type", varchar(32)),
272
+ install_id: column("install_id", varchar(255)).collate(insightsTextCollations),
273
+ user_id: column("user_id", varchar(255)).collate(insightsTextCollations).nullable(),
264
274
  from_release_id: uuid("from_release_id").nullable(),
265
275
  from_bundle_id: uuid("from_bundle_id").nullable(),
266
276
  to_release_id: uuid("to_release_id").nullable(),
267
277
  to_bundle_id: uuid("to_bundle_id"),
268
- platform: stringColumn("platform"),
278
+ platform: stringColumn("platform").collate(insightsTextCollations),
269
279
  app_version: stringColumn("app_version"),
270
- channel: stringColumn("channel"),
271
- cohort: stringColumn("cohort"),
272
- update_strategy: stringColumn("update_strategy").nullable(),
273
- fingerprint_hash: stringColumn("fingerprint_hash").nullable(),
274
- sdk_version: stringColumn("sdk_version").nullable(),
280
+ channel: stringColumn("channel").collate(insightsTextCollations),
281
+ metadata: json("metadata"),
275
282
  received_at_ms: float("received_at_ms")
276
283
  }, {
277
284
  indexes: [
278
285
  index("bundle_events_received_at_idx", ["received_at_ms", "id"]),
279
- index("bundle_events_install_idx", [
286
+ index("bundle_events_latest_idx", [
280
287
  "install_id",
281
288
  "received_at_ms",
282
289
  "id"
283
290
  ]),
284
- index("bundle_events_user_id_idx", [
285
- "user_id",
286
- "received_at_ms",
287
- "id"
288
- ]),
289
- index("bundle_events_username_idx", [
290
- "username",
291
- "received_at_ms",
292
- "id"
293
- ]),
294
- index("bundle_events_to_bundle_idx", [
291
+ index("bundle_events_install_idx", [
292
+ "install_id",
295
293
  "type",
296
- "to_bundle_id",
297
294
  "received_at_ms",
298
295
  "id"
299
296
  ]),
300
297
  index("bundle_events_from_bundle_idx", [
301
298
  "type",
299
+ "platform",
300
+ "channel",
302
301
  "from_bundle_id",
303
302
  "received_at_ms",
304
303
  "id"
305
- ]),
306
- index("bundle_events_to_release_idx", [
307
- "type",
308
- "to_release_id",
309
- "received_at_ms",
310
- "id"
311
- ]),
312
- index("bundle_events_from_release_idx", [
304
+ ], insightsProviders),
305
+ index("bundle_events_to_bundle_idx", [
313
306
  "type",
314
- "from_release_id",
307
+ "platform",
308
+ "channel",
309
+ "to_bundle_id",
315
310
  "received_at_ms",
316
311
  "id"
317
- ])
312
+ ], insightsProviders)
318
313
  ],
319
314
  checks: [
320
315
  check({
321
316
  name: "bundle_events_type_check",
322
- expression: "type in ('UPDATE_APPLIED', 'RECOVERED', 'RELEASE_ADOPTED', 'UNCHANGED')",
317
+ expression: "type in ('UPDATE_DOWNLOADED', 'UPDATE_APPLIED', 'RECOVERED', 'UNCHANGED')",
323
318
  sqliteInline: true
324
319
  }),
325
320
  check({
@@ -329,7 +324,7 @@ const bundleEventsV100 = table("bundle_events", {
329
324
  }),
330
325
  check({
331
326
  name: "bundle_events_shape_check",
332
- expression: "((type in ('UPDATE_APPLIED', 'RECOVERED', 'RELEASE_ADOPTED')) and from_bundle_id is not null and update_strategy is not null and update_strategy in ('fingerprint', 'appVersion')) or (type = 'UNCHANGED' and from_bundle_id is null and update_strategy is null)",
327
+ expression: "((type in ('UPDATE_DOWNLOADED', 'UPDATE_APPLIED', 'RECOVERED')) and from_bundle_id is not null) or (type = 'UNCHANGED' and from_bundle_id is null)",
333
328
  sqliteInline: true
334
329
  }),
335
330
  check({
@@ -339,6 +334,38 @@ const bundleEventsV100 = table("bundle_events", {
339
334
  })
340
335
  ]
341
336
  });
337
+ const bundleEventHeadsV100 = table("bundle_event_heads", {
338
+ install_id: idColumn("install_id", varchar(255)).collate(insightsTextCollations),
339
+ id: uuid("id"),
340
+ received_at_ms: float("received_at_ms"),
341
+ user_id: column("user_id", varchar(255)).collate(insightsTextCollations).nullable(),
342
+ platform: stringColumn("platform").collate(insightsTextCollations),
343
+ channel: stringColumn("channel").collate(insightsTextCollations),
344
+ type: column("type", varchar(32)),
345
+ from_bundle_id: uuid("from_bundle_id").nullable(),
346
+ to_bundle_id: uuid("to_bundle_id")
347
+ }, { indexes: [
348
+ index("bundle_event_heads_user_idx", ["user_id", "install_id"]),
349
+ index("bundle_event_heads_scope_idx", [
350
+ "platform",
351
+ "channel",
352
+ "received_at_ms"
353
+ ], insightsProviders),
354
+ index("bundle_event_heads_from_idx", [
355
+ "type",
356
+ "platform",
357
+ "channel",
358
+ "from_bundle_id",
359
+ "received_at_ms"
360
+ ], insightsProviders),
361
+ index("bundle_event_heads_to_idx", [
362
+ "type",
363
+ "platform",
364
+ "channel",
365
+ "to_bundle_id",
366
+ "received_at_ms"
367
+ ], insightsProviders)
368
+ ] });
342
369
  const v1_0_0 = schema({
343
370
  version: "1.0.0",
344
371
  settingsTable: HOT_UPDATER_SETTINGS_TABLE,
@@ -349,9 +376,10 @@ const v1_0_0 = schema({
349
376
  releasesV100,
350
377
  releaseCatalogsV100,
351
378
  bundleEventsV100,
379
+ bundleEventHeadsV100,
352
380
  apiKeysV100,
353
381
  createSettingsTable("1.0.0")
354
382
  ]
355
383
  });
356
384
  //#endregion
357
- export { apiKeysV100, bundleEventsV100, bundlePatchesV100, bundlesV100, channelsV100, releaseCatalogsV100, releasesV100, v1_0_0 };
385
+ export { apiKeysV100, bundleEventHeadsV100, bundleEventsV100, bundlePatchesV100, bundlesV100, channelsV100, releaseCatalogsV100, releasesV100, v1_0_0 };
@@ -1,4 +1,3 @@
1
- require("./_virtual/_rolldown/runtime.cjs");
2
1
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
3
2
  //#region src/storageAccess.ts
4
3
  const assertRemoteUrl = (value) => {
@@ -1,7 +1,6 @@
1
1
  import { HotUpdaterAPI } from "../createHotUpdaterCore.cjs";
2
2
  import { Bundle, Bundle as Bundle$2 } from "@hot-updater/core";
3
3
  import { ChannelRow } from "@hot-updater/plugin-core";
4
-
5
4
  //#region src/types/index.d.ts
6
5
  interface PaginationInfo {
7
6
  total: number;
@@ -1,7 +1,6 @@
1
1
  import { HotUpdaterAPI } from "../createHotUpdaterCore.mjs";
2
2
  import { ChannelRow } from "@hot-updater/plugin-core";
3
3
  import { Bundle as Bundle$1, Bundle as Bundle$2 } from "@hot-updater/core";
4
-
5
4
  //#region src/types/index.d.ts
6
5
  interface PaginationInfo {
7
6
  total: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hot-updater/server",
3
- "version": "1.0.0-rc.0",
3
+ "version": "1.0.0-rc.14",
4
4
  "type": "module",
5
5
  "description": "React Native OTA solution for self-hosted",
6
6
  "sideEffects": false,
@@ -54,10 +54,10 @@
54
54
  },
55
55
  "dependencies": {
56
56
  "rou3": "0.7.9",
57
- "verkit": "0.3.2",
58
- "@hot-updater/plugin-core": "1.0.0-rc.0",
59
- "@hot-updater/bsdiff": "1.0.0-rc.0",
60
- "@hot-updater/core": "1.0.0-rc.0"
57
+ "verkit": "0.4.0",
58
+ "@hot-updater/bsdiff": "1.0.0-rc.14",
59
+ "@hot-updater/core": "1.0.0-rc.14",
60
+ "@hot-updater/plugin-core": "1.0.0-rc.14"
61
61
  },
62
62
  "peerDependencies": {
63
63
  "@prisma/client": "*",
@@ -91,8 +91,8 @@
91
91
  "mongodb": "6.20.0",
92
92
  "msw": "^2.7.0",
93
93
  "uuidv7": "^1.0.2",
94
- "@hot-updater/standalone": "1.0.0-rc.0",
95
- "@hot-updater/test-utils": "1.0.0-rc.0"
94
+ "@hot-updater/standalone": "1.0.0-rc.14",
95
+ "@hot-updater/test-utils": "1.0.0-rc.14"
96
96
  },
97
97
  "scripts": {
98
98
  "build": "tsdown",
@@ -70,7 +70,6 @@ export const DATABASE_PLUGIN_TEST_SCHEMA_SQL = `
70
70
  type text not null,
71
71
  install_id text not null,
72
72
  user_id text,
73
- username text,
74
73
  from_release_id text,
75
74
  from_bundle_id text,
76
75
  to_release_id text,
@@ -78,12 +77,22 @@ export const DATABASE_PLUGIN_TEST_SCHEMA_SQL = `
78
77
  platform text not null,
79
78
  app_version text not null,
80
79
  channel text not null,
81
- cohort text not null,
82
- update_strategy text,
83
- fingerprint_hash text,
84
- sdk_version text,
80
+ metadata jsonb not null,
85
81
  received_at_ms integer not null
86
82
  );
83
+ create table bundle_event_heads (
84
+ install_id text primary key,
85
+ id text not null,
86
+ received_at_ms integer not null,
87
+ user_id text,
88
+ platform text not null,
89
+ channel text not null,
90
+ type text not null,
91
+ from_bundle_id text,
92
+ to_bundle_id text not null
93
+ );
94
+ create index bundle_event_heads_user_idx on bundle_event_heads(user_id, install_id);
95
+ create index bundle_event_heads_scope_idx on bundle_event_heads(platform, channel, received_at_ms);
87
96
  create table api_keys (
88
97
  id text primary key,
89
98
  hash text not null unique,
@@ -96,6 +105,7 @@ export const DATABASE_PLUGIN_TEST_SCHEMA_SQL = `
96
105
  `;
97
106
 
98
107
  export const DATABASE_PLUGIN_TEST_RESET_SQL = `
108
+ delete from bundle_event_heads;
99
109
  delete from bundle_events;
100
110
  delete from api_keys;
101
111
  delete from bundle_patches;
@@ -1,3 +1,7 @@
1
+ import {
2
+ isDatabaseBundleEventMetadata,
3
+ type BundleEventRow,
4
+ } from "@hot-updater/plugin-core";
1
5
  import type {
2
6
  BundleRow,
3
7
  ReleaseCatalogRow,
@@ -212,3 +216,23 @@ export const escapeLikePattern = (value: string): string =>
212
216
 
213
217
  export const escapeGlobPattern = (value: string): string =>
214
218
  value.replaceAll("[", "[[]").replaceAll("*", "[*]").replaceAll("?", "[?]");
219
+
220
+ export type StoredBundleEventRow = Omit<BundleEventRow, "metadata"> & {
221
+ readonly metadata: unknown;
222
+ };
223
+ export const fromStoredBundleEventRow = (
224
+ row: StoredBundleEventRow,
225
+ ): BundleEventRow => {
226
+ const metadata =
227
+ typeof row.metadata === "string" ? parseJson(row.metadata) : row.metadata;
228
+ if (!isDatabaseBundleEventMetadata(metadata))
229
+ throw new StoredBundleRowError("Invalid event metadata field.");
230
+ return { ...row, metadata } as BundleEventRow;
231
+ };
232
+ export const toStoredBundleEventRow = (
233
+ row: BundleEventRow,
234
+ provider: ORMSQLProvider,
235
+ ): StoredBundleEventRow =>
236
+ provider === "mysql" || provider === "sqlite"
237
+ ? { ...row, metadata: JSON.stringify(row.metadata) }
238
+ : row;