@hot-updater/server 1.0.0-rc.1 → 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 (191) 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 +10 -3
  5. package/dist/adapters/drizzle.d.cts +0 -1
  6. package/dist/adapters/drizzle.d.mts +0 -1
  7. package/dist/adapters/drizzle.mjs +11 -3
  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 +24 -9
  48. package/dist/createHotUpdaterCore.d.cts +1 -1
  49. package/dist/createHotUpdaterCore.d.mts +1 -1
  50. package/dist/createHotUpdaterCore.mjs +23 -9
  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.d.cts +1 -2
  82. package/dist/handler.d.mts +1 -2
  83. package/dist/handlerReleaseCatalogRoutes.cjs +0 -1
  84. package/dist/handlerReleaseManagementRoutes.cjs +0 -1
  85. package/dist/handlerTypes.d.cts +0 -1
  86. package/dist/handlerTypes.d.mts +0 -1
  87. package/dist/handlerVersionRoutes.d.cts +1 -0
  88. package/dist/handlerVersionRoutes.d.mts +1 -0
  89. package/dist/index.cjs +1 -1
  90. package/dist/index.d.cts +4 -4
  91. package/dist/index.d.mts +4 -4
  92. package/dist/index.mjs +1 -1
  93. package/dist/insights/domain.d.cts +37 -69
  94. package/dist/insights/domain.d.mts +37 -69
  95. package/dist/insights/errors.cjs +1 -8
  96. package/dist/insights/errors.mjs +2 -8
  97. package/dist/insights/eventInput.cjs +49 -5
  98. package/dist/insights/eventInput.mjs +48 -6
  99. package/dist/insights/provider.cjs +314 -0
  100. package/dist/insights/provider.d.cts +6 -0
  101. package/dist/insights/provider.d.mts +6 -0
  102. package/dist/insights/provider.mjs +314 -0
  103. package/dist/insights/queryInput.cjs +78 -43
  104. package/dist/insights/queryInput.mjs +76 -40
  105. package/dist/insights/routes.cjs +20 -25
  106. package/dist/insights/routes.mjs +22 -27
  107. package/dist/insights/types.d.cts +27 -12
  108. package/dist/insights/types.d.mts +27 -12
  109. package/dist/node.d.cts +0 -1
  110. package/dist/node.d.mts +0 -1
  111. package/dist/package.cjs +1 -1
  112. package/dist/package.mjs +1 -1
  113. package/dist/schema/index.cjs +17 -3
  114. package/dist/schema/index.mjs +4 -4
  115. package/dist/schema/v1_0_0.cjs +72 -30
  116. package/dist/schema/v1_0_0.mjs +72 -31
  117. package/dist/storageAccess.cjs +0 -1
  118. package/dist/types/index.d.cts +0 -1
  119. package/dist/types/index.d.mts +0 -1
  120. package/package.json +7 -7
  121. package/src/adapters/databasePluginTestDatabase.ts +14 -0
  122. package/src/adapters/drizzle.spec.ts +99 -0
  123. package/src/adapters/drizzle.ts +21 -3
  124. package/src/adapters/drizzleCrud.ts +154 -2
  125. package/src/adapters/drizzleLazyDB.ts +17 -3
  126. package/src/adapters/insightsTransaction.ts +32 -0
  127. package/src/adapters/kysely.spec.ts +29 -0
  128. package/src/adapters/kysely.ts +10 -1
  129. package/src/adapters/kyselyCrud.ts +121 -0
  130. package/src/adapters/mongodb.integration.spec.ts +210 -0
  131. package/src/adapters/mongodb.spec.ts +69 -1
  132. package/src/adapters/mongodb.ts +66 -2
  133. package/src/adapters/mongodbCollections.ts +5 -0
  134. package/src/adapters/mongodbQuery.ts +32 -3
  135. package/src/adapters/mongodbReads.ts +69 -0
  136. package/src/adapters/mongodbTestClient.ts +41 -6
  137. package/src/adapters/mongodbTestFilter.ts +4 -1
  138. package/src/adapters/mongodbWrites.ts +27 -0
  139. package/src/adapters/prisma.spec.ts +97 -0
  140. package/src/adapters/prisma.ts +103 -3
  141. package/src/adapters/prismaRows.ts +37 -1
  142. package/src/adapters/prismaTestClient.ts +22 -5
  143. package/src/apiKeys.integration.spec.ts +1 -1
  144. package/src/createHotUpdaterCore.ts +21 -7
  145. package/src/db/databasePluginUpdateCheck.bench.ts +3 -0
  146. package/src/db/fixedMigrator.spec.ts +65 -0
  147. package/src/db/fixedMigratorMongo.spec.ts +56 -9
  148. package/src/db/fixedMigratorMongo.ts +10 -10
  149. package/src/db/index.spec.ts +8 -1
  150. package/src/db/schema/insightsCollation.ts +21 -0
  151. package/src/db/schema/sql.ts +8 -5
  152. package/src/db/schemaGenerators.ts +41 -13
  153. package/src/db/types.spec.ts +8 -0
  154. package/src/db/types.ts +10 -4
  155. package/src/handler-standalone.integration.spec.ts +5 -7
  156. package/src/index.ts +2 -2
  157. package/src/insights/domain.ts +39 -75
  158. package/src/insights/errors.ts +0 -7
  159. package/src/insights/eventInput.ts +60 -3
  160. package/src/insights/insights.integration.spec.ts +254 -17
  161. package/src/insights/provider.spec.ts +385 -0
  162. package/src/insights/provider.ts +591 -0
  163. package/src/insights/queryInput.ts +112 -73
  164. package/src/insights/routes.ts +37 -56
  165. package/src/insights/types.ts +47 -36
  166. package/src/schema/dsl-all-versions.spec.ts +3 -1
  167. package/src/schema/v1_0_0.spec.ts +77 -3
  168. package/src/schema/v1_0_0.ts +94 -30
  169. package/dist/insights/bounded/activeOverview.cjs +0 -87
  170. package/dist/insights/bounded/activeOverview.mjs +0 -85
  171. package/dist/insights/bounded/installationSearch.cjs +0 -42
  172. package/dist/insights/bounded/installationSearch.mjs +0 -42
  173. package/dist/insights/bounded/persistence.cjs +0 -39
  174. package/dist/insights/bounded/persistence.mjs +0 -38
  175. package/dist/insights/bounded/provider.cjs +0 -170
  176. package/dist/insights/bounded/provider.d.cts +0 -7
  177. package/dist/insights/bounded/provider.d.mts +0 -7
  178. package/dist/insights/bounded/provider.mjs +0 -170
  179. package/dist/insights/bounded/scan.cjs +0 -144
  180. package/dist/insights/bounded/scan.mjs +0 -138
  181. package/dist/insights/persistence.d.cts +0 -6
  182. package/dist/insights/persistence.d.mts +0 -6
  183. package/src/insights/bounded/activeOverview.spec.ts +0 -189
  184. package/src/insights/bounded/activeOverview.ts +0 -148
  185. package/src/insights/bounded/installationSearch.spec.ts +0 -130
  186. package/src/insights/bounded/installationSearch.ts +0 -69
  187. package/src/insights/bounded/persistence.ts +0 -43
  188. package/src/insights/bounded/provider.spec.ts +0 -219
  189. package/src/insights/bounded/provider.ts +0 -229
  190. package/src/insights/bounded/scan.ts +0 -235
  191. package/src/insights/persistence.ts +0 -10
@@ -14,15 +14,7 @@ type CreateBundleEventRequestBase = {
14
14
  readonly toReleaseId: string | null;
15
15
  };
16
16
  type CreateBundleEventRequest = (CreateBundleEventRequestBase & {
17
- readonly type: "UPDATE_APPLIED";
18
- readonly fromBundleId: string;
19
- readonly updateStrategy: "fingerprint" | "appVersion";
20
- }) | (CreateBundleEventRequestBase & {
21
- readonly type: "RECOVERED";
22
- readonly fromBundleId: string;
23
- readonly updateStrategy: "fingerprint" | "appVersion";
24
- }) | (CreateBundleEventRequestBase & {
25
- readonly type: "RELEASE_ADOPTED";
17
+ readonly type: "UPDATE_APPLIED" | "RECOVERED" | "RELEASE_ADOPTED";
26
18
  readonly fromBundleId: string;
27
19
  readonly updateStrategy: "fingerprint" | "appVersion";
28
20
  }) | (CreateBundleEventRequestBase & {
@@ -30,92 +22,68 @@ type CreateBundleEventRequest = (CreateBundleEventRequestBase & {
30
22
  readonly fromBundleId: null;
31
23
  readonly updateStrategy: null;
32
24
  });
33
- type BundleEventSummary = {
34
- readonly installed: number;
35
- readonly recovered: number;
36
- };
37
- type BundleEventSummaryByBundle = BundleEventSummary & {
38
- readonly bundleId: string;
39
- };
40
- type BundleEventInsightsWindow = "24h" | "7d" | "30d" | "all";
41
25
  type ActiveInstallationWindow = "24h" | "7d" | "30d";
42
- type InstallationSearchRow = {
26
+ type EventHistoryRow = {
27
+ readonly id: string;
43
28
  readonly installId: string;
29
+ readonly type: "UPDATE_APPLIED" | "RECOVERED" | "RELEASE_ADOPTED" | "UNCHANGED";
30
+ readonly fromBundleId: string | null;
31
+ readonly toBundleId: string;
44
32
  readonly username: string | null;
45
33
  readonly userId: string | null;
46
- readonly lastKnownBundleId: string;
47
- readonly latestStatus: "UPDATE_APPLIED" | "RECOVERED" | "RELEASE_ADOPTED" | "UNCHANGED";
48
34
  readonly platform: "ios" | "android";
49
35
  readonly appVersion: string;
50
36
  readonly channel: string;
51
37
  readonly cohort: string;
52
38
  readonly receivedAtMs: number;
53
39
  };
54
- type InstallationHistoryRow = {
55
- readonly id: string;
40
+ type InstallationHistoryRow = EventHistoryRow & {
56
41
  readonly type: "UPDATE_APPLIED" | "RECOVERED";
57
42
  readonly fromBundleId: string;
58
- readonly toBundleId: string;
43
+ };
44
+ type InstallationRow = {
45
+ readonly installId: string;
59
46
  readonly username: string | null;
60
47
  readonly userId: string | null;
48
+ readonly lastKnownBundleId: string;
49
+ readonly latestStatus: EventHistoryRow["type"];
61
50
  readonly platform: "ios" | "android";
62
51
  readonly appVersion: string;
63
52
  readonly channel: string;
64
53
  readonly cohort: string;
65
54
  readonly receivedAtMs: number;
66
55
  };
67
- type OffsetPaginationResult<TData> = {
68
- readonly data: readonly TData[];
69
- readonly pagination: {
70
- readonly total: number;
71
- readonly limit: number;
72
- readonly offset: number;
73
- };
56
+ type CursorPage<T> = {
57
+ readonly data: readonly T[];
58
+ readonly nextCursor: string | null;
74
59
  };
75
- type InsightsSeriesPoint = {
76
- readonly bucketStartMs: number;
77
- readonly value: number;
60
+ type EventCursorPage<T extends EventHistoryRow> = CursorPage<T> & {
61
+ readonly beforeReceivedAtMs: number;
78
62
  };
79
- type InsightsCohortPoint = {
80
- readonly cohort: string;
81
- readonly value: number;
63
+ type InsightsScope = {
64
+ readonly platform: "ios" | "android";
65
+ readonly channel: string;
82
66
  };
83
- type BundleEventInsightsResult = {
84
- readonly summary: BundleEventSummary;
85
- readonly series: {
86
- readonly installed: readonly InsightsSeriesPoint[];
87
- readonly recovered: readonly InsightsSeriesPoint[];
88
- };
89
- readonly cohorts: {
90
- readonly installed: readonly InsightsCohortPoint[];
91
- readonly recovered: readonly InsightsCohortPoint[];
92
- };
93
- readonly recentEvents: OffsetPaginationResult<InstallationHistoryRow>;
67
+ type InsightsBundleSelection = InsightsScope & {
68
+ readonly bundleId: string;
69
+ readonly outcome: "applied" | "recovered" | "adopted";
94
70
  };
95
- type BundleEventOverview = {
96
- readonly trackedInstallations: number;
97
- readonly bundles: readonly {
98
- readonly bundleId: string;
99
- readonly installations: number;
100
- }[];
71
+ type InsightsCountMeasurement = {
72
+ readonly count: number;
73
+ readonly measuredAtMs: number;
101
74
  };
102
- type ActiveInstallationOverview = {
103
- readonly asOfMs: number;
75
+ type ReportingOverview = InsightsScope & {
104
76
  readonly window: ActiveInstallationWindow;
105
- readonly activeInstallations: number;
106
- readonly series: readonly InsightsSeriesPoint[];
107
- readonly bundleSeries: readonly {
77
+ readonly sinceMs: number;
78
+ readonly beforeReceivedAtMs: number;
79
+ readonly reportingInstallations: InsightsCountMeasurement;
80
+ readonly bundle?: {
108
81
  readonly bundleId: string;
109
- readonly series: readonly InsightsSeriesPoint[];
110
- }[];
111
- readonly bundles: readonly {
112
- readonly bundleId: string;
113
- readonly installations: number;
114
- }[];
115
- };
116
- type ActiveInstallationInput = {
117
- readonly window: ActiveInstallationWindow;
118
- readonly userId?: string;
82
+ readonly reportingInstallations: InsightsCountMeasurement;
83
+ readonly appliedReports: InsightsCountMeasurement;
84
+ readonly recoveredReports: InsightsCountMeasurement;
85
+ readonly adoptedReports: InsightsCountMeasurement;
86
+ };
119
87
  };
120
88
  //#endregion
121
- export { ActiveInstallationInput, ActiveInstallationOverview, ActiveInstallationWindow, BundleEventInsightsResult, BundleEventInsightsWindow, BundleEventOverview, BundleEventSummary, BundleEventSummaryByBundle, CreateBundleEventRequest, CreateBundleEventRequestBase, InsightsCohortPoint, InsightsSeriesPoint, InstallationHistoryRow, InstallationSearchRow, OffsetPaginationResult };
89
+ export { ActiveInstallationWindow, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsScope, InstallationHistoryRow, InstallationRow, ReportingOverview };
@@ -14,15 +14,7 @@ type CreateBundleEventRequestBase = {
14
14
  readonly toReleaseId: string | null;
15
15
  };
16
16
  type CreateBundleEventRequest = (CreateBundleEventRequestBase & {
17
- readonly type: "UPDATE_APPLIED";
18
- readonly fromBundleId: string;
19
- readonly updateStrategy: "fingerprint" | "appVersion";
20
- }) | (CreateBundleEventRequestBase & {
21
- readonly type: "RECOVERED";
22
- readonly fromBundleId: string;
23
- readonly updateStrategy: "fingerprint" | "appVersion";
24
- }) | (CreateBundleEventRequestBase & {
25
- readonly type: "RELEASE_ADOPTED";
17
+ readonly type: "UPDATE_APPLIED" | "RECOVERED" | "RELEASE_ADOPTED";
26
18
  readonly fromBundleId: string;
27
19
  readonly updateStrategy: "fingerprint" | "appVersion";
28
20
  }) | (CreateBundleEventRequestBase & {
@@ -30,92 +22,68 @@ type CreateBundleEventRequest = (CreateBundleEventRequestBase & {
30
22
  readonly fromBundleId: null;
31
23
  readonly updateStrategy: null;
32
24
  });
33
- type BundleEventSummary = {
34
- readonly installed: number;
35
- readonly recovered: number;
36
- };
37
- type BundleEventSummaryByBundle = BundleEventSummary & {
38
- readonly bundleId: string;
39
- };
40
- type BundleEventInsightsWindow = "24h" | "7d" | "30d" | "all";
41
25
  type ActiveInstallationWindow = "24h" | "7d" | "30d";
42
- type InstallationSearchRow = {
26
+ type EventHistoryRow = {
27
+ readonly id: string;
43
28
  readonly installId: string;
29
+ readonly type: "UPDATE_APPLIED" | "RECOVERED" | "RELEASE_ADOPTED" | "UNCHANGED";
30
+ readonly fromBundleId: string | null;
31
+ readonly toBundleId: string;
44
32
  readonly username: string | null;
45
33
  readonly userId: string | null;
46
- readonly lastKnownBundleId: string;
47
- readonly latestStatus: "UPDATE_APPLIED" | "RECOVERED" | "RELEASE_ADOPTED" | "UNCHANGED";
48
34
  readonly platform: "ios" | "android";
49
35
  readonly appVersion: string;
50
36
  readonly channel: string;
51
37
  readonly cohort: string;
52
38
  readonly receivedAtMs: number;
53
39
  };
54
- type InstallationHistoryRow = {
55
- readonly id: string;
40
+ type InstallationHistoryRow = EventHistoryRow & {
56
41
  readonly type: "UPDATE_APPLIED" | "RECOVERED";
57
42
  readonly fromBundleId: string;
58
- readonly toBundleId: string;
43
+ };
44
+ type InstallationRow = {
45
+ readonly installId: string;
59
46
  readonly username: string | null;
60
47
  readonly userId: string | null;
48
+ readonly lastKnownBundleId: string;
49
+ readonly latestStatus: EventHistoryRow["type"];
61
50
  readonly platform: "ios" | "android";
62
51
  readonly appVersion: string;
63
52
  readonly channel: string;
64
53
  readonly cohort: string;
65
54
  readonly receivedAtMs: number;
66
55
  };
67
- type OffsetPaginationResult<TData> = {
68
- readonly data: readonly TData[];
69
- readonly pagination: {
70
- readonly total: number;
71
- readonly limit: number;
72
- readonly offset: number;
73
- };
56
+ type CursorPage<T> = {
57
+ readonly data: readonly T[];
58
+ readonly nextCursor: string | null;
74
59
  };
75
- type InsightsSeriesPoint = {
76
- readonly bucketStartMs: number;
77
- readonly value: number;
60
+ type EventCursorPage<T extends EventHistoryRow> = CursorPage<T> & {
61
+ readonly beforeReceivedAtMs: number;
78
62
  };
79
- type InsightsCohortPoint = {
80
- readonly cohort: string;
81
- readonly value: number;
63
+ type InsightsScope = {
64
+ readonly platform: "ios" | "android";
65
+ readonly channel: string;
82
66
  };
83
- type BundleEventInsightsResult = {
84
- readonly summary: BundleEventSummary;
85
- readonly series: {
86
- readonly installed: readonly InsightsSeriesPoint[];
87
- readonly recovered: readonly InsightsSeriesPoint[];
88
- };
89
- readonly cohorts: {
90
- readonly installed: readonly InsightsCohortPoint[];
91
- readonly recovered: readonly InsightsCohortPoint[];
92
- };
93
- readonly recentEvents: OffsetPaginationResult<InstallationHistoryRow>;
67
+ type InsightsBundleSelection = InsightsScope & {
68
+ readonly bundleId: string;
69
+ readonly outcome: "applied" | "recovered" | "adopted";
94
70
  };
95
- type BundleEventOverview = {
96
- readonly trackedInstallations: number;
97
- readonly bundles: readonly {
98
- readonly bundleId: string;
99
- readonly installations: number;
100
- }[];
71
+ type InsightsCountMeasurement = {
72
+ readonly count: number;
73
+ readonly measuredAtMs: number;
101
74
  };
102
- type ActiveInstallationOverview = {
103
- readonly asOfMs: number;
75
+ type ReportingOverview = InsightsScope & {
104
76
  readonly window: ActiveInstallationWindow;
105
- readonly activeInstallations: number;
106
- readonly series: readonly InsightsSeriesPoint[];
107
- readonly bundleSeries: readonly {
77
+ readonly sinceMs: number;
78
+ readonly beforeReceivedAtMs: number;
79
+ readonly reportingInstallations: InsightsCountMeasurement;
80
+ readonly bundle?: {
108
81
  readonly bundleId: string;
109
- readonly series: readonly InsightsSeriesPoint[];
110
- }[];
111
- readonly bundles: readonly {
112
- readonly bundleId: string;
113
- readonly installations: number;
114
- }[];
115
- };
116
- type ActiveInstallationInput = {
117
- readonly window: ActiveInstallationWindow;
118
- readonly userId?: string;
82
+ readonly reportingInstallations: InsightsCountMeasurement;
83
+ readonly appliedReports: InsightsCountMeasurement;
84
+ readonly recoveredReports: InsightsCountMeasurement;
85
+ readonly adoptedReports: InsightsCountMeasurement;
86
+ };
119
87
  };
120
88
  //#endregion
121
- export { ActiveInstallationInput, ActiveInstallationOverview, ActiveInstallationWindow, BundleEventInsightsResult, BundleEventInsightsWindow, BundleEventOverview, BundleEventSummary, BundleEventSummaryByBundle, CreateBundleEventRequest, CreateBundleEventRequestBase, InsightsCohortPoint, InsightsSeriesPoint, InstallationHistoryRow, InstallationSearchRow, OffsetPaginationResult };
89
+ export { ActiveInstallationWindow, CreateBundleEventRequest, CreateBundleEventRequestBase, CursorPage, EventCursorPage, EventHistoryRow, InsightsBundleSelection, InsightsCountMeasurement, InsightsScope, InstallationHistoryRow, InstallationRow, ReportingOverview };
@@ -1,15 +1,9 @@
1
1
  //#region src/insights/errors.ts
2
- var InsightsScanLimitExceededError = class extends Error {
3
- constructor(limit) {
4
- super(`Insights event scan exceeded ${limit} rows.`);
5
- this.limit = limit;
6
- this.name = "InsightsScanLimitExceededError";
7
- }
8
- };
9
2
  var InsightsBadRequestError = class extends Error {
10
3
  name = "InsightsBadRequestError";
11
4
  };
12
5
  var InsightsPayloadTooLargeError = class extends Error {
6
+ maximumBytes;
13
7
  name = "InsightsPayloadTooLargeError";
14
8
  constructor(maximumBytes) {
15
9
  super(`Event payload exceeds ${maximumBytes} bytes`);
@@ -19,4 +13,3 @@ var InsightsPayloadTooLargeError = class extends Error {
19
13
  //#endregion
20
14
  exports.InsightsBadRequestError = InsightsBadRequestError;
21
15
  exports.InsightsPayloadTooLargeError = InsightsPayloadTooLargeError;
22
- exports.InsightsScanLimitExceededError = InsightsScanLimitExceededError;
@@ -1,15 +1,9 @@
1
1
  //#region src/insights/errors.ts
2
- var InsightsScanLimitExceededError = class extends Error {
3
- constructor(limit) {
4
- super(`Insights event scan exceeded ${limit} rows.`);
5
- this.limit = limit;
6
- this.name = "InsightsScanLimitExceededError";
7
- }
8
- };
9
2
  var InsightsBadRequestError = class extends Error {
10
3
  name = "InsightsBadRequestError";
11
4
  };
12
5
  var InsightsPayloadTooLargeError = class extends Error {
6
+ maximumBytes;
13
7
  name = "InsightsPayloadTooLargeError";
14
8
  constructor(maximumBytes) {
15
9
  super(`Event payload exceeds ${maximumBytes} bytes`);
@@ -17,4 +11,4 @@ var InsightsPayloadTooLargeError = class extends Error {
17
11
  }
18
12
  };
19
13
  //#endregion
20
- export { InsightsBadRequestError, InsightsPayloadTooLargeError, InsightsScanLimitExceededError };
14
+ export { InsightsBadRequestError, InsightsPayloadTooLargeError };
@@ -1,8 +1,10 @@
1
1
  const require_errors = require("./errors.cjs");
2
+ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
2
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,13 +26,18 @@ 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.InsightsBadRequestError(`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);
@@ -66,9 +73,9 @@ function requireEvent(payload) {
66
73
  const platform = requireStringField(payload, "platform");
67
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"),
@@ -107,5 +114,42 @@ function requireEvent(payload) {
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
1
  import { InsightsBadRequestError, InsightsPayloadTooLargeError } from "./errors.mjs";
2
+ import { createUUIDv7 } from "@hot-updater/plugin-core";
2
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,13 +26,18 @@ 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 InsightsBadRequestError(`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);
@@ -66,9 +73,9 @@ function requireEvent(payload) {
66
73
  const platform = requireStringField(payload, "platform");
67
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"),
@@ -107,5 +114,40 @@ function requireEvent(payload) {
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 };