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

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 (210) 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 +0 -1
  4. package/dist/adapters/drizzle.cjs +11 -4
  5. package/dist/adapters/drizzle.d.cts +0 -1
  6. package/dist/adapters/drizzle.d.mts +0 -1
  7. package/dist/adapters/drizzle.mjs +12 -4
  8. package/dist/adapters/drizzleCrud.cjs +62 -1
  9. package/dist/adapters/drizzleCrud.mjs +61 -2
  10. package/dist/adapters/drizzleLazyDB.cjs +6 -1
  11. package/dist/adapters/drizzleLazyDB.mjs +6 -1
  12. package/dist/adapters/drizzleQuery.cjs +3 -2
  13. package/dist/adapters/drizzleQuery.mjs +3 -1
  14. package/dist/adapters/insightsTransaction.cjs +22 -0
  15. package/dist/adapters/insightsTransaction.mjs +22 -0
  16. package/dist/adapters/kysely.cjs +2 -1
  17. package/dist/adapters/kysely.d.cts +0 -1
  18. package/dist/adapters/kysely.d.mts +0 -1
  19. package/dist/adapters/kysely.mjs +3 -1
  20. package/dist/adapters/kyselyCrud.cjs +54 -3
  21. package/dist/adapters/kyselyCrud.mjs +54 -3
  22. package/dist/adapters/kyselyQuery.cjs +2 -2
  23. package/dist/adapters/kyselyQuery.mjs +2 -1
  24. package/dist/adapters/mongodb.cjs +27 -1
  25. package/dist/adapters/mongodb.d.cts +1 -1
  26. package/dist/adapters/mongodb.d.mts +1 -1
  27. package/dist/adapters/mongodb.mjs +28 -1
  28. package/dist/adapters/mongodbCollections.cjs +2 -0
  29. package/dist/adapters/mongodbCollections.mjs +2 -0
  30. package/dist/adapters/mongodbQuery.cjs +21 -4
  31. package/dist/adapters/mongodbQuery.mjs +21 -5
  32. package/dist/adapters/mongodbReads.cjs +91 -29
  33. package/dist/adapters/mongodbReads.mjs +92 -29
  34. package/dist/adapters/mongodbWrites.cjs +16 -2
  35. package/dist/adapters/mongodbWrites.mjs +18 -3
  36. package/dist/adapters/prisma.cjs +55 -7
  37. package/dist/adapters/prisma.d.cts +0 -1
  38. package/dist/adapters/prisma.d.mts +0 -1
  39. package/dist/adapters/prisma.mjs +56 -7
  40. package/dist/adapters/prismaQuery.cjs +0 -1
  41. package/dist/adapters/prismaRows.cjs +22 -1
  42. package/dist/adapters/prismaRows.mjs +22 -1
  43. package/dist/apiKeys.cjs +6 -2
  44. package/dist/apiKeys.d.cts +0 -1
  45. package/dist/apiKeys.d.mts +0 -1
  46. package/dist/apiKeys.mjs +3 -3
  47. package/dist/createHotUpdaterCore.cjs +27 -12
  48. package/dist/createHotUpdaterCore.d.cts +8 -8
  49. package/dist/createHotUpdaterCore.d.mts +8 -8
  50. package/dist/createHotUpdaterCore.mjs +26 -12
  51. package/dist/db/createBundleDiff.cjs +2 -2
  52. package/dist/db/createBundleDiff.d.cts +1 -5
  53. package/dist/db/createBundleDiff.d.mts +1 -5
  54. package/dist/db/databasePluginCore.cjs +0 -1
  55. package/dist/db/fixedMigrator.cjs +2 -2
  56. package/dist/db/fixedMigrator.mjs +2 -2
  57. package/dist/db/fixedMigratorMongo.cjs +6 -4
  58. package/dist/db/fixedMigratorMongo.mjs +6 -4
  59. package/dist/db/index.d.cts +0 -1
  60. package/dist/db/index.d.mts +0 -1
  61. package/dist/db/releaseCatalog.cjs +0 -1
  62. package/dist/db/releaseCatalog.d.cts +0 -1
  63. package/dist/db/releaseCatalog.d.mts +0 -1
  64. package/dist/db/schema/insightsCollation.cjs +14 -0
  65. package/dist/db/schema/insightsCollation.mjs +14 -0
  66. package/dist/db/schema/sql.cjs +11 -7
  67. package/dist/db/schema/sql.mjs +8 -8
  68. package/dist/db/schemaGenerators.cjs +28 -9
  69. package/dist/db/schemaGenerators.mjs +28 -9
  70. package/dist/db/schemaReadiness.cjs +2 -0
  71. package/dist/db/schemaReadiness.d.cts +1 -0
  72. package/dist/db/schemaReadiness.d.mts +1 -0
  73. package/dist/db/schemaReadiness.mjs +2 -0
  74. package/dist/db/sqlMigrationExecution.cjs +1 -1
  75. package/dist/db/sqlMigrationExecution.mjs +1 -0
  76. package/dist/db/types.cjs +3 -1
  77. package/dist/db/types.d.cts +3 -6
  78. package/dist/db/types.d.mts +3 -6
  79. package/dist/db/types.mjs +2 -2
  80. package/dist/db/updateArtifacts.cjs +0 -1
  81. package/dist/handler.cjs +5 -5
  82. package/dist/handler.d.cts +1 -2
  83. package/dist/handler.d.mts +1 -2
  84. package/dist/handler.mjs +5 -5
  85. package/dist/handlerReleaseCatalogRoutes.cjs +0 -1
  86. package/dist/handlerReleaseManagementRoutes.cjs +0 -1
  87. package/dist/handlerTypes.d.cts +0 -1
  88. package/dist/handlerTypes.d.mts +0 -1
  89. package/dist/handlerVersionRoutes.d.cts +1 -0
  90. package/dist/handlerVersionRoutes.d.mts +1 -0
  91. package/dist/index.cjs +2 -2
  92. package/dist/index.d.cts +4 -4
  93. package/dist/index.d.mts +4 -4
  94. package/dist/index.mjs +2 -2
  95. package/dist/insights/domain.d.cts +89 -0
  96. package/dist/insights/domain.d.mts +89 -0
  97. package/dist/insights/errors.cjs +15 -0
  98. package/dist/insights/errors.mjs +14 -0
  99. package/dist/{analytics → insights}/eventInput.cjs +58 -14
  100. package/dist/{analytics → insights}/eventInput.mjs +58 -16
  101. package/dist/insights/provider.cjs +314 -0
  102. package/dist/insights/provider.d.cts +6 -0
  103. package/dist/insights/provider.d.mts +6 -0
  104. package/dist/insights/provider.mjs +314 -0
  105. package/dist/insights/queryInput.cjs +93 -0
  106. package/dist/insights/queryInput.mjs +91 -0
  107. package/dist/insights/routes.cjs +58 -0
  108. package/dist/insights/routes.mjs +56 -0
  109. package/dist/insights/types.d.cts +32 -0
  110. package/dist/insights/types.d.mts +32 -0
  111. package/dist/node.d.cts +0 -1
  112. package/dist/node.d.mts +0 -1
  113. package/dist/package.cjs +1 -1
  114. package/dist/package.mjs +1 -1
  115. package/dist/schema/index.cjs +17 -3
  116. package/dist/schema/index.mjs +4 -4
  117. package/dist/schema/v1_0_0.cjs +72 -30
  118. package/dist/schema/v1_0_0.mjs +72 -31
  119. package/dist/storageAccess.cjs +0 -1
  120. package/dist/types/index.d.cts +0 -1
  121. package/dist/types/index.d.mts +0 -1
  122. package/package.json +7 -7
  123. package/src/adapters/databasePluginTestDatabase.ts +14 -0
  124. package/src/adapters/drizzle.spec.ts +99 -0
  125. package/src/adapters/drizzle.ts +22 -4
  126. package/src/adapters/drizzleCrud.ts +154 -2
  127. package/src/adapters/drizzleLazyDB.ts +17 -3
  128. package/src/adapters/insightsTransaction.ts +32 -0
  129. package/src/adapters/kysely.spec.ts +29 -0
  130. package/src/adapters/kysely.ts +10 -1
  131. package/src/adapters/kyselyCrud.ts +121 -0
  132. package/src/adapters/mongodb.integration.spec.ts +210 -0
  133. package/src/adapters/mongodb.spec.ts +69 -1
  134. package/src/adapters/mongodb.ts +66 -2
  135. package/src/adapters/mongodbCollections.ts +5 -0
  136. package/src/adapters/mongodbQuery.ts +32 -3
  137. package/src/adapters/mongodbReads.ts +69 -0
  138. package/src/adapters/mongodbTestClient.ts +41 -6
  139. package/src/adapters/mongodbTestFilter.ts +4 -1
  140. package/src/adapters/mongodbWrites.ts +27 -0
  141. package/src/adapters/prisma.spec.ts +97 -0
  142. package/src/adapters/prisma.ts +103 -3
  143. package/src/adapters/prismaRows.ts +37 -1
  144. package/src/adapters/prismaTestClient.ts +22 -5
  145. package/src/apiKeys.integration.spec.ts +3 -3
  146. package/src/createHotUpdaterCore.ts +30 -16
  147. package/src/db/databasePluginUpdateCheck.bench.ts +3 -0
  148. package/src/db/fixedMigrator.spec.ts +65 -0
  149. package/src/db/fixedMigratorMongo.spec.ts +56 -9
  150. package/src/db/fixedMigratorMongo.ts +10 -10
  151. package/src/db/index.spec.ts +8 -1
  152. package/src/db/schema/insightsCollation.ts +21 -0
  153. package/src/db/schema/sql.ts +8 -5
  154. package/src/db/schemaGenerators.ts +41 -13
  155. package/src/db/types.spec.ts +11 -3
  156. package/src/db/types.ts +13 -7
  157. package/src/handler-standalone.integration.spec.ts +6 -8
  158. package/src/handler.ts +12 -12
  159. package/src/index.ts +3 -3
  160. package/src/insights/domain.ts +103 -0
  161. package/src/insights/errors.ts +11 -0
  162. package/src/{analytics → insights}/eventInput.ts +71 -14
  163. package/src/insights/insights.integration.spec.ts +381 -0
  164. package/src/insights/provider.spec.ts +385 -0
  165. package/src/insights/provider.ts +591 -0
  166. package/src/insights/queryInput.ts +141 -0
  167. package/src/insights/routes.ts +104 -0
  168. package/src/insights/types.ts +55 -0
  169. package/src/schema/dsl-all-versions.spec.ts +3 -1
  170. package/src/schema/v1_0_0.spec.ts +77 -3
  171. package/src/schema/v1_0_0.ts +94 -30
  172. package/dist/analytics/bounded/activeOverview.cjs +0 -87
  173. package/dist/analytics/bounded/activeOverview.mjs +0 -85
  174. package/dist/analytics/bounded/installationSearch.cjs +0 -42
  175. package/dist/analytics/bounded/installationSearch.mjs +0 -42
  176. package/dist/analytics/bounded/persistence.cjs +0 -39
  177. package/dist/analytics/bounded/persistence.mjs +0 -38
  178. package/dist/analytics/bounded/provider.cjs +0 -170
  179. package/dist/analytics/bounded/provider.d.cts +0 -7
  180. package/dist/analytics/bounded/provider.d.mts +0 -7
  181. package/dist/analytics/bounded/provider.mjs +0 -170
  182. package/dist/analytics/bounded/scan.cjs +0 -144
  183. package/dist/analytics/bounded/scan.mjs +0 -138
  184. package/dist/analytics/domain.d.cts +0 -121
  185. package/dist/analytics/domain.d.mts +0 -121
  186. package/dist/analytics/errors.cjs +0 -22
  187. package/dist/analytics/errors.mjs +0 -20
  188. package/dist/analytics/persistence.d.cts +0 -6
  189. package/dist/analytics/persistence.d.mts +0 -6
  190. package/dist/analytics/queryInput.cjs +0 -58
  191. package/dist/analytics/queryInput.mjs +0 -55
  192. package/dist/analytics/routes.cjs +0 -63
  193. package/dist/analytics/routes.mjs +0 -61
  194. package/dist/analytics/types.d.cts +0 -17
  195. package/dist/analytics/types.d.mts +0 -17
  196. package/src/analytics/analytics.integration.spec.ts +0 -144
  197. package/src/analytics/bounded/activeOverview.spec.ts +0 -189
  198. package/src/analytics/bounded/activeOverview.ts +0 -148
  199. package/src/analytics/bounded/installationSearch.spec.ts +0 -130
  200. package/src/analytics/bounded/installationSearch.ts +0 -69
  201. package/src/analytics/bounded/persistence.ts +0 -43
  202. package/src/analytics/bounded/provider.spec.ts +0 -219
  203. package/src/analytics/bounded/provider.ts +0 -229
  204. package/src/analytics/bounded/scan.ts +0 -235
  205. package/src/analytics/domain.ts +0 -139
  206. package/src/analytics/errors.ts +0 -18
  207. package/src/analytics/persistence.ts +0 -10
  208. package/src/analytics/queryInput.ts +0 -102
  209. package/src/analytics/routes.ts +0 -123
  210. package/src/analytics/types.ts +0 -44
@@ -1,4 +1,3 @@
1
- require("./_virtual/_rolldown/runtime.cjs");
2
1
  const require_handlerParameters = require("./handlerParameters.cjs");
3
2
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
4
3
  //#region src/handlerReleaseCatalogRoutes.ts
@@ -1,4 +1,3 @@
1
- require("./_virtual/_rolldown/runtime.cjs");
2
1
  const require_handlerErrors = require("./handlerErrors.cjs");
3
2
  const require_handlerParameters = require("./handlerParameters.cjs");
4
3
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
@@ -2,7 +2,6 @@ import { ReleaseCatalogRequest } from "./db/releaseCatalog.cjs";
2
2
  import { PaginatedResult } from "./types/index.cjs";
3
3
  import { ArtifactInfo, Bundle, ReleaseCatalog } from "@hot-updater/core";
4
4
  import { ChannelDeleteInput, ChannelDeleteResult, ChannelInsertInput, ChannelInsertResult, ChannelRow, DatabaseBundleQueryOptions, DatabaseCommit, DatabaseCommitResult, ReleaseCatalogMutationPreflight, ReleaseCatalogMutationResult, ReleaseCatalogRebuildResult, ReleaseCatalogRow, ReleasePolicyPatch, ReleaseRow } from "@hot-updater/plugin-core";
5
-
6
5
  //#region src/handlerTypes.d.ts
7
6
  interface HandlerAPI {
8
7
  getReleaseCatalog?: (input: ReleaseCatalogRequest) => Promise<ReleaseCatalog | null>;
@@ -2,7 +2,6 @@ import { ReleaseCatalogRequest } from "./db/releaseCatalog.mjs";
2
2
  import { PaginatedResult } from "./types/index.mjs";
3
3
  import { ChannelDeleteInput, ChannelDeleteResult, ChannelInsertInput, ChannelInsertResult, ChannelRow, DatabaseBundleQueryOptions, DatabaseCommit, DatabaseCommitResult, ReleaseCatalogMutationPreflight, ReleaseCatalogMutationResult, ReleaseCatalogRebuildResult, ReleaseCatalogRow, ReleasePolicyPatch, ReleaseRow } from "@hot-updater/plugin-core";
4
4
  import { ArtifactInfo, Bundle as Bundle$1, ReleaseCatalog } from "@hot-updater/core";
5
-
6
5
  //#region src/handlerTypes.d.ts
7
6
  interface HandlerAPI {
8
7
  getReleaseCatalog?: (input: ReleaseCatalogRequest) => Promise<ReleaseCatalog | null>;
@@ -1,3 +1,4 @@
1
+ import "./handlerTypes.cjs";
1
2
  //#region src/handlerVersionRoutes.d.ts
2
3
  declare const HOT_UPDATER_INFRASTRUCTURE_GENERATION = 1;
3
4
  //#endregion
@@ -1,3 +1,4 @@
1
+ import "./handlerTypes.mjs";
1
2
  //#region src/handlerVersionRoutes.d.ts
2
3
  declare const HOT_UPDATER_INFRASTRUCTURE_GENERATION = 1;
3
4
  //#endregion
package/dist/index.cjs CHANGED
@@ -2,15 +2,15 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_version = require("./version.cjs");
3
3
  const require_handlerVersionRoutes = require("./handlerVersionRoutes.cjs");
4
4
  const require_handler = require("./handler.cjs");
5
- const require_provider = require("./analytics/bounded/provider.cjs");
5
+ const require_provider = require("./insights/provider.cjs");
6
6
  const require_apiKeys = require("./apiKeys.cjs");
7
7
  const require_createHotUpdaterCore = require("./createHotUpdaterCore.cjs");
8
8
  exports.API_KEY_HEADER_NAME = require_apiKeys.API_KEY_HEADER_NAME;
9
9
  exports.HOT_UPDATER_INFRASTRUCTURE_GENERATION = require_handlerVersionRoutes.HOT_UPDATER_INFRASTRUCTURE_GENERATION;
10
10
  exports.HOT_UPDATER_SERVER_VERSION = require_version.HOT_UPDATER_SERVER_VERSION;
11
- exports.createAnalyticsProvider = require_provider.createAnalyticsProvider;
12
11
  exports.createApiKey = require_apiKeys.createApiKey;
13
12
  exports.createHandlers = require_handler.createHandlers;
14
13
  exports.createHotUpdater = require_createHotUpdaterCore.createHotUpdater;
14
+ exports.createInsightsProvider = require_provider.createInsightsProvider;
15
15
  exports.provisionApiKey = require_apiKeys.provisionApiKey;
16
16
  exports.registerApiKey = require_apiKeys.registerApiKey;
package/dist/index.d.cts CHANGED
@@ -1,11 +1,11 @@
1
- import { ActiveInstallationInput, ActiveInstallationOverview, ActiveInstallationWindow, AnalyticsCohortPoint, AnalyticsSeriesPoint, BundleEventAnalyticsResult, BundleEventAnalyticsWindow, BundleEventOverview, BundleEventSummary, BundleEventSummaryByBundle, CreateBundleEventRequest, CreateBundleEventRequestBase, InstallationHistoryRow, InstallationSearchRow, OffsetPaginationResult } from "./analytics/domain.cjs";
2
- import { AnalyticsProvider } from "./analytics/types.cjs";
3
1
  import { API_KEY_HEADER_NAME, ApiKeyManagementAPI, ApiKeyMetadata, CreatedApiKey, createApiKey, provisionApiKey, registerApiKey } from "./apiKeys.cjs";
4
2
  import { HandlerAPI, HotUpdaterHandler, HotUpdaterHandlers } from "./handlerTypes.cjs";
3
+ import { ActiveInstallationWindow, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsScope, InstallationHistoryRow, InstallationRow, ReportingOverview } from "./insights/domain.cjs";
4
+ import { InsightsEventPageInput, InsightsInstallationEventPageInput, InsightsProvider, InsightsUserInstallationPageInput } from "./insights/types.cjs";
5
5
  import { createHandlers } from "./handler.cjs";
6
6
  import { ClientAccessPolicy, CreateHotUpdaterOptions, HotUpdaterAPI, RuntimeHotUpdaterAPI, createHotUpdater } from "./createHotUpdaterCore.cjs";
7
7
  import { Bundle, ChannelsResponse, DataResponse, Paginated, PaginatedResult, PaginationInfo, PaginationOptions } from "./types/index.cjs";
8
8
  import { HOT_UPDATER_SERVER_VERSION } from "./version.cjs";
9
- import { createAnalyticsProvider } from "./analytics/bounded/provider.cjs";
9
+ import { createInsightsProvider } from "./insights/provider.cjs";
10
10
  import { HOT_UPDATER_INFRASTRUCTURE_GENERATION } from "./handlerVersionRoutes.cjs";
11
- export { API_KEY_HEADER_NAME, ActiveInstallationInput, ActiveInstallationOverview, ActiveInstallationWindow, AnalyticsCohortPoint, type AnalyticsProvider, AnalyticsSeriesPoint, type ApiKeyManagementAPI, type ApiKeyMetadata, Bundle, BundleEventAnalyticsResult, BundleEventAnalyticsWindow, BundleEventOverview, BundleEventSummary, BundleEventSummaryByBundle, ChannelsResponse, type ClientAccessPolicy, CreateBundleEventRequest, CreateBundleEventRequestBase, type CreateHotUpdaterOptions, type CreatedApiKey, DataResponse, HOT_UPDATER_INFRASTRUCTURE_GENERATION, HOT_UPDATER_SERVER_VERSION, type HandlerAPI, type HotUpdaterAPI, type HotUpdaterHandler, type HotUpdaterHandlers, InstallationHistoryRow, InstallationSearchRow, OffsetPaginationResult, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, type RuntimeHotUpdaterAPI, createAnalyticsProvider, createApiKey, createHandlers, createHotUpdater, provisionApiKey, registerApiKey };
11
+ export { API_KEY_HEADER_NAME, type ActiveInstallationWindow, type ApiKeyManagementAPI, type ApiKeyMetadata, type Bundle, ChannelsResponse, type ClientAccessPolicy, type CreateBundleEventRequest, type CreateBundleEventRequestBase, type CreateHotUpdaterOptions, type CreatedApiKey, type CursorPage, DataResponse, type EventCursorPage, type EventHistoryRow, HOT_UPDATER_INFRASTRUCTURE_GENERATION, HOT_UPDATER_SERVER_VERSION, type HandlerAPI, type HotUpdaterAPI, type HotUpdaterHandler, type HotUpdaterHandlers, type InsightsBundleSelection, type InsightsCountMeasurement, type InsightsEventPageInput, type InsightsInstallationEventPageInput, type InsightsProvider, type InsightsScope, type InsightsUserInstallationPageInput, type InstallationHistoryRow, type InstallationRow, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, type ReportingOverview, type RuntimeHotUpdaterAPI, createApiKey, createHandlers, createHotUpdater, createInsightsProvider, provisionApiKey, registerApiKey };
package/dist/index.d.mts CHANGED
@@ -1,11 +1,11 @@
1
- import { ActiveInstallationInput, ActiveInstallationOverview, ActiveInstallationWindow, AnalyticsCohortPoint, AnalyticsSeriesPoint, BundleEventAnalyticsResult, BundleEventAnalyticsWindow, BundleEventOverview, BundleEventSummary, BundleEventSummaryByBundle, CreateBundleEventRequest, CreateBundleEventRequestBase, InstallationHistoryRow, InstallationSearchRow, OffsetPaginationResult } from "./analytics/domain.mjs";
2
- import { AnalyticsProvider } from "./analytics/types.mjs";
3
1
  import { API_KEY_HEADER_NAME, ApiKeyManagementAPI, ApiKeyMetadata, CreatedApiKey, createApiKey, provisionApiKey, registerApiKey } from "./apiKeys.mjs";
4
2
  import { HandlerAPI, HotUpdaterHandler, HotUpdaterHandlers } from "./handlerTypes.mjs";
3
+ import { ActiveInstallationWindow, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsScope, InstallationHistoryRow, InstallationRow, ReportingOverview } from "./insights/domain.mjs";
4
+ import { InsightsEventPageInput, InsightsInstallationEventPageInput, InsightsProvider, InsightsUserInstallationPageInput } from "./insights/types.mjs";
5
5
  import { createHandlers } from "./handler.mjs";
6
6
  import { ClientAccessPolicy, CreateHotUpdaterOptions, HotUpdaterAPI, RuntimeHotUpdaterAPI, createHotUpdater } from "./createHotUpdaterCore.mjs";
7
7
  import { Bundle, ChannelsResponse, DataResponse, Paginated, PaginatedResult, PaginationInfo, PaginationOptions } from "./types/index.mjs";
8
8
  import { HOT_UPDATER_SERVER_VERSION } from "./version.mjs";
9
- import { createAnalyticsProvider } from "./analytics/bounded/provider.mjs";
9
+ import { createInsightsProvider } from "./insights/provider.mjs";
10
10
  import { HOT_UPDATER_INFRASTRUCTURE_GENERATION } from "./handlerVersionRoutes.mjs";
11
- export { API_KEY_HEADER_NAME, ActiveInstallationInput, ActiveInstallationOverview, ActiveInstallationWindow, AnalyticsCohortPoint, type AnalyticsProvider, AnalyticsSeriesPoint, type ApiKeyManagementAPI, type ApiKeyMetadata, Bundle, BundleEventAnalyticsResult, BundleEventAnalyticsWindow, BundleEventOverview, BundleEventSummary, BundleEventSummaryByBundle, ChannelsResponse, type ClientAccessPolicy, CreateBundleEventRequest, CreateBundleEventRequestBase, type CreateHotUpdaterOptions, type CreatedApiKey, DataResponse, HOT_UPDATER_INFRASTRUCTURE_GENERATION, HOT_UPDATER_SERVER_VERSION, type HandlerAPI, type HotUpdaterAPI, type HotUpdaterHandler, type HotUpdaterHandlers, InstallationHistoryRow, InstallationSearchRow, OffsetPaginationResult, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, type RuntimeHotUpdaterAPI, createAnalyticsProvider, createApiKey, createHandlers, createHotUpdater, provisionApiKey, registerApiKey };
11
+ export { API_KEY_HEADER_NAME, type ActiveInstallationWindow, type ApiKeyManagementAPI, type ApiKeyMetadata, type Bundle, ChannelsResponse, type ClientAccessPolicy, type CreateBundleEventRequest, type CreateBundleEventRequestBase, type CreateHotUpdaterOptions, type CreatedApiKey, type CursorPage, DataResponse, type EventCursorPage, type EventHistoryRow, HOT_UPDATER_INFRASTRUCTURE_GENERATION, HOT_UPDATER_SERVER_VERSION, type HandlerAPI, type HotUpdaterAPI, type HotUpdaterHandler, type HotUpdaterHandlers, type InsightsBundleSelection, type InsightsCountMeasurement, type InsightsEventPageInput, type InsightsInstallationEventPageInput, type InsightsProvider, type InsightsScope, type InsightsUserInstallationPageInput, type InstallationHistoryRow, type InstallationRow, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, type ReportingOverview, type RuntimeHotUpdaterAPI, createApiKey, createHandlers, createHotUpdater, createInsightsProvider, provisionApiKey, registerApiKey };
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { HOT_UPDATER_SERVER_VERSION } from "./version.mjs";
2
2
  import { HOT_UPDATER_INFRASTRUCTURE_GENERATION } from "./handlerVersionRoutes.mjs";
3
3
  import { createHandlers } from "./handler.mjs";
4
- import { createAnalyticsProvider } from "./analytics/bounded/provider.mjs";
4
+ import { createInsightsProvider } from "./insights/provider.mjs";
5
5
  import { API_KEY_HEADER_NAME, createApiKey, provisionApiKey, registerApiKey } from "./apiKeys.mjs";
6
6
  import { createHotUpdater } from "./createHotUpdaterCore.mjs";
7
- export { API_KEY_HEADER_NAME, HOT_UPDATER_INFRASTRUCTURE_GENERATION, HOT_UPDATER_SERVER_VERSION, createAnalyticsProvider, createApiKey, createHandlers, createHotUpdater, provisionApiKey, registerApiKey };
7
+ export { API_KEY_HEADER_NAME, HOT_UPDATER_INFRASTRUCTURE_GENERATION, HOT_UPDATER_SERVER_VERSION, createApiKey, createHandlers, createHotUpdater, createInsightsProvider, provisionApiKey, registerApiKey };
@@ -0,0 +1,89 @@
1
+ //#region src/insights/domain.d.ts
2
+ type CreateBundleEventRequestBase = {
3
+ readonly installId: string;
4
+ readonly toBundleId: string;
5
+ readonly userId?: string;
6
+ readonly username?: string;
7
+ readonly platform: "ios" | "android";
8
+ readonly appVersion: string;
9
+ readonly channel: string;
10
+ readonly cohort: string;
11
+ readonly fingerprintHash: string | null;
12
+ readonly sdkVersion?: string | null;
13
+ readonly fromReleaseId: string | null;
14
+ readonly toReleaseId: string | null;
15
+ };
16
+ type CreateBundleEventRequest = (CreateBundleEventRequestBase & {
17
+ readonly type: "UPDATE_APPLIED" | "RECOVERED" | "RELEASE_ADOPTED";
18
+ readonly fromBundleId: string;
19
+ readonly updateStrategy: "fingerprint" | "appVersion";
20
+ }) | (CreateBundleEventRequestBase & {
21
+ readonly type: "UNCHANGED";
22
+ readonly fromBundleId: null;
23
+ readonly updateStrategy: null;
24
+ });
25
+ type ActiveInstallationWindow = "24h" | "7d" | "30d";
26
+ type EventHistoryRow = {
27
+ readonly id: string;
28
+ readonly installId: string;
29
+ readonly type: "UPDATE_APPLIED" | "RECOVERED" | "RELEASE_ADOPTED" | "UNCHANGED";
30
+ readonly fromBundleId: string | null;
31
+ readonly toBundleId: string;
32
+ readonly username: string | null;
33
+ readonly userId: string | null;
34
+ readonly platform: "ios" | "android";
35
+ readonly appVersion: string;
36
+ readonly channel: string;
37
+ readonly cohort: string;
38
+ readonly receivedAtMs: number;
39
+ };
40
+ type InstallationHistoryRow = EventHistoryRow & {
41
+ readonly type: "UPDATE_APPLIED" | "RECOVERED";
42
+ readonly fromBundleId: string;
43
+ };
44
+ type InstallationRow = {
45
+ readonly installId: string;
46
+ readonly username: string | null;
47
+ readonly userId: string | null;
48
+ readonly lastKnownBundleId: string;
49
+ readonly latestStatus: EventHistoryRow["type"];
50
+ readonly platform: "ios" | "android";
51
+ readonly appVersion: string;
52
+ readonly channel: string;
53
+ readonly cohort: string;
54
+ readonly receivedAtMs: number;
55
+ };
56
+ type CursorPage<T> = {
57
+ readonly data: readonly T[];
58
+ readonly nextCursor: string | null;
59
+ };
60
+ type EventCursorPage<T extends EventHistoryRow> = CursorPage<T> & {
61
+ readonly beforeReceivedAtMs: number;
62
+ };
63
+ type InsightsScope = {
64
+ readonly platform: "ios" | "android";
65
+ readonly channel: string;
66
+ };
67
+ type InsightsBundleSelection = InsightsScope & {
68
+ readonly bundleId: string;
69
+ readonly outcome: "applied" | "recovered" | "adopted";
70
+ };
71
+ type InsightsCountMeasurement = {
72
+ readonly count: number;
73
+ readonly measuredAtMs: number;
74
+ };
75
+ type ReportingOverview = InsightsScope & {
76
+ readonly window: ActiveInstallationWindow;
77
+ readonly sinceMs: number;
78
+ readonly beforeReceivedAtMs: number;
79
+ readonly reportingInstallations: InsightsCountMeasurement;
80
+ readonly bundle?: {
81
+ readonly bundleId: string;
82
+ readonly reportingInstallations: InsightsCountMeasurement;
83
+ readonly appliedReports: InsightsCountMeasurement;
84
+ readonly recoveredReports: InsightsCountMeasurement;
85
+ readonly adoptedReports: InsightsCountMeasurement;
86
+ };
87
+ };
88
+ //#endregion
89
+ export { ActiveInstallationWindow, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsScope, InstallationHistoryRow, InstallationRow, ReportingOverview };
@@ -0,0 +1,89 @@
1
+ //#region src/insights/domain.d.ts
2
+ type CreateBundleEventRequestBase = {
3
+ readonly installId: string;
4
+ readonly toBundleId: string;
5
+ readonly userId?: string;
6
+ readonly username?: string;
7
+ readonly platform: "ios" | "android";
8
+ readonly appVersion: string;
9
+ readonly channel: string;
10
+ readonly cohort: string;
11
+ readonly fingerprintHash: string | null;
12
+ readonly sdkVersion?: string | null;
13
+ readonly fromReleaseId: string | null;
14
+ readonly toReleaseId: string | null;
15
+ };
16
+ type CreateBundleEventRequest = (CreateBundleEventRequestBase & {
17
+ readonly type: "UPDATE_APPLIED" | "RECOVERED" | "RELEASE_ADOPTED";
18
+ readonly fromBundleId: string;
19
+ readonly updateStrategy: "fingerprint" | "appVersion";
20
+ }) | (CreateBundleEventRequestBase & {
21
+ readonly type: "UNCHANGED";
22
+ readonly fromBundleId: null;
23
+ readonly updateStrategy: null;
24
+ });
25
+ type ActiveInstallationWindow = "24h" | "7d" | "30d";
26
+ type EventHistoryRow = {
27
+ readonly id: string;
28
+ readonly installId: string;
29
+ readonly type: "UPDATE_APPLIED" | "RECOVERED" | "RELEASE_ADOPTED" | "UNCHANGED";
30
+ readonly fromBundleId: string | null;
31
+ readonly toBundleId: string;
32
+ readonly username: string | null;
33
+ readonly userId: string | null;
34
+ readonly platform: "ios" | "android";
35
+ readonly appVersion: string;
36
+ readonly channel: string;
37
+ readonly cohort: string;
38
+ readonly receivedAtMs: number;
39
+ };
40
+ type InstallationHistoryRow = EventHistoryRow & {
41
+ readonly type: "UPDATE_APPLIED" | "RECOVERED";
42
+ readonly fromBundleId: string;
43
+ };
44
+ type InstallationRow = {
45
+ readonly installId: string;
46
+ readonly username: string | null;
47
+ readonly userId: string | null;
48
+ readonly lastKnownBundleId: string;
49
+ readonly latestStatus: EventHistoryRow["type"];
50
+ readonly platform: "ios" | "android";
51
+ readonly appVersion: string;
52
+ readonly channel: string;
53
+ readonly cohort: string;
54
+ readonly receivedAtMs: number;
55
+ };
56
+ type CursorPage<T> = {
57
+ readonly data: readonly T[];
58
+ readonly nextCursor: string | null;
59
+ };
60
+ type EventCursorPage<T extends EventHistoryRow> = CursorPage<T> & {
61
+ readonly beforeReceivedAtMs: number;
62
+ };
63
+ type InsightsScope = {
64
+ readonly platform: "ios" | "android";
65
+ readonly channel: string;
66
+ };
67
+ type InsightsBundleSelection = InsightsScope & {
68
+ readonly bundleId: string;
69
+ readonly outcome: "applied" | "recovered" | "adopted";
70
+ };
71
+ type InsightsCountMeasurement = {
72
+ readonly count: number;
73
+ readonly measuredAtMs: number;
74
+ };
75
+ type ReportingOverview = InsightsScope & {
76
+ readonly window: ActiveInstallationWindow;
77
+ readonly sinceMs: number;
78
+ readonly beforeReceivedAtMs: number;
79
+ readonly reportingInstallations: InsightsCountMeasurement;
80
+ readonly bundle?: {
81
+ readonly bundleId: string;
82
+ readonly reportingInstallations: InsightsCountMeasurement;
83
+ readonly appliedReports: InsightsCountMeasurement;
84
+ readonly recoveredReports: InsightsCountMeasurement;
85
+ readonly adoptedReports: InsightsCountMeasurement;
86
+ };
87
+ };
88
+ //#endregion
89
+ export { ActiveInstallationWindow, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsScope, InstallationHistoryRow, InstallationRow, ReportingOverview };
@@ -0,0 +1,15 @@
1
+ //#region src/insights/errors.ts
2
+ var InsightsBadRequestError = class extends Error {
3
+ name = "InsightsBadRequestError";
4
+ };
5
+ var InsightsPayloadTooLargeError = class extends Error {
6
+ maximumBytes;
7
+ name = "InsightsPayloadTooLargeError";
8
+ constructor(maximumBytes) {
9
+ super(`Event payload exceeds ${maximumBytes} bytes`);
10
+ this.maximumBytes = maximumBytes;
11
+ }
12
+ };
13
+ //#endregion
14
+ exports.InsightsBadRequestError = InsightsBadRequestError;
15
+ exports.InsightsPayloadTooLargeError = InsightsPayloadTooLargeError;
@@ -0,0 +1,14 @@
1
+ //#region src/insights/errors.ts
2
+ var InsightsBadRequestError = class extends Error {
3
+ name = "InsightsBadRequestError";
4
+ };
5
+ var InsightsPayloadTooLargeError = class extends Error {
6
+ maximumBytes;
7
+ name = "InsightsPayloadTooLargeError";
8
+ constructor(maximumBytes) {
9
+ super(`Event payload exceeds ${maximumBytes} bytes`);
10
+ this.maximumBytes = maximumBytes;
11
+ }
12
+ };
13
+ //#endregion
14
+ export { InsightsBadRequestError, InsightsPayloadTooLargeError };
@@ -1,8 +1,10 @@
1
1
  const require_errors = require("./errors.cjs");
2
- //#region src/analytics/eventInput.ts
2
+ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
3
+ //#region src/insights/eventInput.ts
3
4
  const MAX_EVENT_STRING_LENGTH = 1024;
4
- const EVENT_BODY_MAX_BYTES = 16 * 1024;
5
- const eventKeys = new Set([
5
+ const MAX_IDENTITY_LENGTH = 255;
6
+ const EVENT_BODY_MAX_BYTES = 16384;
7
+ const eventKeys = /* @__PURE__ */ new Set([
6
8
  "type",
7
9
  "installId",
8
10
  "toBundleId",
@@ -24,17 +26,22 @@ function isRecord(value) {
24
26
  }
25
27
  function requireStringField(payload, key) {
26
28
  const value = payload[key];
27
- if (typeof value !== "string" || value.length === 0 || value.length > MAX_EVENT_STRING_LENGTH) throw new require_errors.AnalyticsBadRequestError(`Invalid event field: ${key}`);
29
+ if (typeof value !== "string" || value.length === 0 || value.length > MAX_EVENT_STRING_LENGTH || new TextDecoder("utf-8", { ignoreBOM: true }).decode(new TextEncoder().encode(value)) !== value) throw new require_errors.InsightsBadRequestError(`Invalid event field: ${key}`);
28
30
  return value;
29
31
  }
30
32
  function requireNullableStringField(payload, key) {
31
33
  if (payload[key] === null) return null;
32
34
  return requireStringField(payload, key);
33
35
  }
36
+ function requireIdentityField(payload, key) {
37
+ const value = requireStringField(payload, key);
38
+ if (value.length > MAX_IDENTITY_LENGTH) throw new require_errors.InsightsBadRequestError(`Invalid event field: ${key}`);
39
+ return value;
40
+ }
34
41
  async function readBoundedText(request) {
35
42
  const contentLength = request.headers.get("content-length");
36
43
  const declaredByteLength = Number(contentLength);
37
- if (contentLength !== null && Number.isSafeInteger(declaredByteLength) && declaredByteLength > 16384) throw new require_errors.AnalyticsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
44
+ if (contentLength !== null && Number.isSafeInteger(declaredByteLength) && declaredByteLength > 16384) throw new require_errors.InsightsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
38
45
  if (request.body === null) return "";
39
46
  const reader = request.body.getReader();
40
47
  const decoder = new TextDecoder();
@@ -46,7 +53,7 @@ async function readBoundedText(request) {
46
53
  byteLength += result.value.byteLength;
47
54
  if (byteLength > 16384) {
48
55
  await reader.cancel();
49
- throw new require_errors.AnalyticsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
56
+ throw new require_errors.InsightsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
50
57
  }
51
58
  text += decoder.decode(result.value, { stream: true });
52
59
  }
@@ -57,18 +64,18 @@ async function parseJson(request) {
57
64
  try {
58
65
  return JSON.parse(text);
59
66
  } catch (error) {
60
- if (error instanceof SyntaxError) throw new require_errors.AnalyticsBadRequestError("Invalid event payload");
67
+ if (error instanceof SyntaxError) throw new require_errors.InsightsBadRequestError("Invalid event payload");
61
68
  throw error;
62
69
  }
63
70
  }
64
71
  function requireEvent(payload) {
65
- if (!isRecord(payload) || Object.keys(payload).some((key) => !eventKeys.has(key))) throw new require_errors.AnalyticsBadRequestError("Invalid event payload");
72
+ if (!isRecord(payload) || Object.keys(payload).some((key) => !eventKeys.has(key))) throw new require_errors.InsightsBadRequestError("Invalid event payload");
66
73
  const platform = requireStringField(payload, "platform");
67
- if (platform !== "ios" && platform !== "android") throw new require_errors.AnalyticsBadRequestError("Invalid event field: platform");
74
+ if (platform !== "ios" && platform !== "android") throw new require_errors.InsightsBadRequestError("Invalid event field: platform");
68
75
  const base = {
69
- installId: requireStringField(payload, "installId"),
76
+ installId: requireIdentityField(payload, "installId"),
70
77
  toBundleId: requireStringField(payload, "toBundleId"),
71
- ...payload.userId === void 0 ? {} : { userId: requireStringField(payload, "userId") },
78
+ ...payload.userId === void 0 ? {} : { userId: requireIdentityField(payload, "userId") },
72
79
  ...payload.username === void 0 ? {} : { username: requireStringField(payload, "username") },
73
80
  platform,
74
81
  appVersion: requireStringField(payload, "appVersion"),
@@ -85,7 +92,7 @@ function requireEvent(payload) {
85
92
  case "RECOVERED":
86
93
  case "RELEASE_ADOPTED": {
87
94
  const updateStrategy = requireStringField(payload, "updateStrategy");
88
- if (updateStrategy !== "fingerprint" && updateStrategy !== "appVersion") throw new require_errors.AnalyticsBadRequestError("Invalid event field: updateStrategy");
95
+ if (updateStrategy !== "fingerprint" && updateStrategy !== "appVersion") throw new require_errors.InsightsBadRequestError("Invalid event field: updateStrategy");
89
96
  return {
90
97
  ...base,
91
98
  type,
@@ -94,18 +101,55 @@ function requireEvent(payload) {
94
101
  };
95
102
  }
96
103
  case "UNCHANGED":
97
- if (payload.fromBundleId !== null || payload.updateStrategy !== null) throw new require_errors.AnalyticsBadRequestError("Invalid unchanged event shape");
104
+ if (payload.fromBundleId !== null || payload.updateStrategy !== null) throw new require_errors.InsightsBadRequestError("Invalid unchanged event shape");
98
105
  return {
99
106
  ...base,
100
107
  type,
101
108
  fromBundleId: null,
102
109
  updateStrategy: null
103
110
  };
104
- default: throw new require_errors.AnalyticsBadRequestError("Invalid event field: type");
111
+ default: throw new require_errors.InsightsBadRequestError("Invalid event field: type");
105
112
  }
106
113
  }
107
114
  async function parseBundleEventRequest(request) {
108
115
  return requireEvent(await parseJson(request));
109
116
  }
117
+ function createBundleEventRow(input) {
118
+ input = requireEvent(input);
119
+ const base = {
120
+ app_version: input.appVersion,
121
+ channel: input.channel,
122
+ cohort: input.cohort,
123
+ fingerprint_hash: input.fingerprintHash,
124
+ from_release_id: input.fromReleaseId,
125
+ id: (0, _hot_updater_plugin_core.createUUIDv7)(),
126
+ install_id: input.installId,
127
+ platform: input.platform,
128
+ received_at_ms: Date.now(),
129
+ sdk_version: input.sdkVersion ?? null,
130
+ to_bundle_id: input.toBundleId,
131
+ to_release_id: input.toReleaseId,
132
+ user_id: input.userId ?? null,
133
+ username: input.username ?? null
134
+ };
135
+ switch (input.type) {
136
+ case "UPDATE_APPLIED":
137
+ case "RECOVERED":
138
+ case "RELEASE_ADOPTED": return {
139
+ ...base,
140
+ from_bundle_id: input.fromBundleId,
141
+ type: input.type,
142
+ update_strategy: input.updateStrategy
143
+ };
144
+ case "UNCHANGED": return {
145
+ ...base,
146
+ from_bundle_id: null,
147
+ type: input.type,
148
+ update_strategy: null
149
+ };
150
+ }
151
+ }
110
152
  //#endregion
153
+ exports.EVENT_BODY_MAX_BYTES = EVENT_BODY_MAX_BYTES;
154
+ exports.createBundleEventRow = createBundleEventRow;
111
155
  exports.parseBundleEventRequest = parseBundleEventRequest;
@@ -1,8 +1,10 @@
1
- import { AnalyticsBadRequestError, AnalyticsPayloadTooLargeError } from "./errors.mjs";
2
- //#region src/analytics/eventInput.ts
1
+ import { InsightsBadRequestError, InsightsPayloadTooLargeError } from "./errors.mjs";
2
+ import { createUUIDv7 } from "@hot-updater/plugin-core";
3
+ //#region src/insights/eventInput.ts
3
4
  const MAX_EVENT_STRING_LENGTH = 1024;
4
- const EVENT_BODY_MAX_BYTES = 16 * 1024;
5
- const eventKeys = new Set([
5
+ const MAX_IDENTITY_LENGTH = 255;
6
+ const EVENT_BODY_MAX_BYTES = 16384;
7
+ const eventKeys = /* @__PURE__ */ new Set([
6
8
  "type",
7
9
  "installId",
8
10
  "toBundleId",
@@ -24,17 +26,22 @@ function isRecord(value) {
24
26
  }
25
27
  function requireStringField(payload, key) {
26
28
  const value = payload[key];
27
- if (typeof value !== "string" || value.length === 0 || value.length > MAX_EVENT_STRING_LENGTH) throw new AnalyticsBadRequestError(`Invalid event field: ${key}`);
29
+ if (typeof value !== "string" || value.length === 0 || value.length > MAX_EVENT_STRING_LENGTH || new TextDecoder("utf-8", { ignoreBOM: true }).decode(new TextEncoder().encode(value)) !== value) throw new InsightsBadRequestError(`Invalid event field: ${key}`);
28
30
  return value;
29
31
  }
30
32
  function requireNullableStringField(payload, key) {
31
33
  if (payload[key] === null) return null;
32
34
  return requireStringField(payload, key);
33
35
  }
36
+ function requireIdentityField(payload, key) {
37
+ const value = requireStringField(payload, key);
38
+ if (value.length > MAX_IDENTITY_LENGTH) throw new InsightsBadRequestError(`Invalid event field: ${key}`);
39
+ return value;
40
+ }
34
41
  async function readBoundedText(request) {
35
42
  const contentLength = request.headers.get("content-length");
36
43
  const declaredByteLength = Number(contentLength);
37
- if (contentLength !== null && Number.isSafeInteger(declaredByteLength) && declaredByteLength > 16384) throw new AnalyticsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
44
+ if (contentLength !== null && Number.isSafeInteger(declaredByteLength) && declaredByteLength > 16384) throw new InsightsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
38
45
  if (request.body === null) return "";
39
46
  const reader = request.body.getReader();
40
47
  const decoder = new TextDecoder();
@@ -46,7 +53,7 @@ async function readBoundedText(request) {
46
53
  byteLength += result.value.byteLength;
47
54
  if (byteLength > 16384) {
48
55
  await reader.cancel();
49
- throw new AnalyticsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
56
+ throw new InsightsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
50
57
  }
51
58
  text += decoder.decode(result.value, { stream: true });
52
59
  }
@@ -57,18 +64,18 @@ async function parseJson(request) {
57
64
  try {
58
65
  return JSON.parse(text);
59
66
  } catch (error) {
60
- if (error instanceof SyntaxError) throw new AnalyticsBadRequestError("Invalid event payload");
67
+ if (error instanceof SyntaxError) throw new InsightsBadRequestError("Invalid event payload");
61
68
  throw error;
62
69
  }
63
70
  }
64
71
  function requireEvent(payload) {
65
- if (!isRecord(payload) || Object.keys(payload).some((key) => !eventKeys.has(key))) throw new AnalyticsBadRequestError("Invalid event payload");
72
+ if (!isRecord(payload) || Object.keys(payload).some((key) => !eventKeys.has(key))) throw new InsightsBadRequestError("Invalid event payload");
66
73
  const platform = requireStringField(payload, "platform");
67
- if (platform !== "ios" && platform !== "android") throw new AnalyticsBadRequestError("Invalid event field: platform");
74
+ if (platform !== "ios" && platform !== "android") throw new InsightsBadRequestError("Invalid event field: platform");
68
75
  const base = {
69
- installId: requireStringField(payload, "installId"),
76
+ installId: requireIdentityField(payload, "installId"),
70
77
  toBundleId: requireStringField(payload, "toBundleId"),
71
- ...payload.userId === void 0 ? {} : { userId: requireStringField(payload, "userId") },
78
+ ...payload.userId === void 0 ? {} : { userId: requireIdentityField(payload, "userId") },
72
79
  ...payload.username === void 0 ? {} : { username: requireStringField(payload, "username") },
73
80
  platform,
74
81
  appVersion: requireStringField(payload, "appVersion"),
@@ -85,7 +92,7 @@ function requireEvent(payload) {
85
92
  case "RECOVERED":
86
93
  case "RELEASE_ADOPTED": {
87
94
  const updateStrategy = requireStringField(payload, "updateStrategy");
88
- if (updateStrategy !== "fingerprint" && updateStrategy !== "appVersion") throw new AnalyticsBadRequestError("Invalid event field: updateStrategy");
95
+ if (updateStrategy !== "fingerprint" && updateStrategy !== "appVersion") throw new InsightsBadRequestError("Invalid event field: updateStrategy");
89
96
  return {
90
97
  ...base,
91
98
  type,
@@ -94,18 +101,53 @@ function requireEvent(payload) {
94
101
  };
95
102
  }
96
103
  case "UNCHANGED":
97
- if (payload.fromBundleId !== null || payload.updateStrategy !== null) throw new AnalyticsBadRequestError("Invalid unchanged event shape");
104
+ if (payload.fromBundleId !== null || payload.updateStrategy !== null) throw new InsightsBadRequestError("Invalid unchanged event shape");
98
105
  return {
99
106
  ...base,
100
107
  type,
101
108
  fromBundleId: null,
102
109
  updateStrategy: null
103
110
  };
104
- default: throw new AnalyticsBadRequestError("Invalid event field: type");
111
+ default: throw new InsightsBadRequestError("Invalid event field: type");
105
112
  }
106
113
  }
107
114
  async function parseBundleEventRequest(request) {
108
115
  return requireEvent(await parseJson(request));
109
116
  }
117
+ function createBundleEventRow(input) {
118
+ input = requireEvent(input);
119
+ const base = {
120
+ app_version: input.appVersion,
121
+ channel: input.channel,
122
+ cohort: input.cohort,
123
+ fingerprint_hash: input.fingerprintHash,
124
+ from_release_id: input.fromReleaseId,
125
+ id: createUUIDv7(),
126
+ install_id: input.installId,
127
+ platform: input.platform,
128
+ received_at_ms: Date.now(),
129
+ sdk_version: input.sdkVersion ?? null,
130
+ to_bundle_id: input.toBundleId,
131
+ to_release_id: input.toReleaseId,
132
+ user_id: input.userId ?? null,
133
+ username: input.username ?? null
134
+ };
135
+ switch (input.type) {
136
+ case "UPDATE_APPLIED":
137
+ case "RECOVERED":
138
+ case "RELEASE_ADOPTED": return {
139
+ ...base,
140
+ from_bundle_id: input.fromBundleId,
141
+ type: input.type,
142
+ update_strategy: input.updateStrategy
143
+ };
144
+ case "UNCHANGED": return {
145
+ ...base,
146
+ from_bundle_id: null,
147
+ type: input.type,
148
+ update_strategy: null
149
+ };
150
+ }
151
+ }
110
152
  //#endregion
111
- export { parseBundleEventRequest };
153
+ export { EVENT_BODY_MAX_BYTES, createBundleEventRow, parseBundleEventRequest };