@hot-updater/server 1.0.0-rc.1 → 1.0.0-rc.16

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 (542) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +1 -1
  2. package/dist/adapters/drizzle.cjs +35 -69
  3. package/dist/adapters/drizzle.d.cts +13 -6
  4. package/dist/adapters/drizzle.d.mts +13 -6
  5. package/dist/adapters/drizzle.mjs +34 -69
  6. package/dist/adapters/drizzleExecutor.cjs +114 -0
  7. package/dist/adapters/drizzleExecutor.d.cts +9 -0
  8. package/dist/adapters/drizzleExecutor.d.mts +9 -0
  9. package/dist/adapters/drizzleExecutor.mjs +112 -0
  10. package/dist/adapters/kysely.cjs +25 -31
  11. package/dist/adapters/kysely.d.cts +10 -7
  12. package/dist/adapters/kysely.d.mts +10 -7
  13. package/dist/adapters/kysely.mjs +25 -31
  14. package/dist/adapters/kyselyExecutor.cjs +32 -0
  15. package/dist/adapters/kyselyExecutor.d.cts +12 -0
  16. package/dist/adapters/kyselyExecutor.d.mts +12 -0
  17. package/dist/adapters/kyselyExecutor.mjs +32 -0
  18. package/dist/adapters/mongodb.cjs +28 -27
  19. package/dist/adapters/mongodb.d.cts +10 -5
  20. package/dist/adapters/mongodb.d.mts +10 -5
  21. package/dist/adapters/mongodb.mjs +28 -27
  22. package/dist/adapters/mongodbAdapter.cjs +174 -0
  23. package/dist/adapters/mongodbAdapter.d.cts +9 -0
  24. package/dist/adapters/mongodbAdapter.d.mts +9 -0
  25. package/dist/adapters/mongodbAdapter.mjs +173 -0
  26. package/dist/adapters/prisma.cjs +38 -220
  27. package/dist/adapters/prisma.d.cts +12 -8
  28. package/dist/adapters/prisma.d.mts +12 -8
  29. package/dist/adapters/prisma.mjs +38 -219
  30. package/dist/adapters/prismaExecutor.cjs +64 -0
  31. package/dist/adapters/prismaExecutor.mjs +64 -0
  32. package/dist/adapters/sqlProviders.cjs +9 -0
  33. package/dist/adapters/sqlProviders.mjs +9 -0
  34. package/dist/apiKeys.cjs +8 -8
  35. package/dist/apiKeys.d.cts +1 -24
  36. package/dist/apiKeys.d.mts +1 -24
  37. package/dist/apiKeys.mjs +5 -9
  38. package/dist/assembly/assemblePlugins.cjs +147 -0
  39. package/dist/assembly/assemblePlugins.d.cts +12 -0
  40. package/dist/assembly/assemblePlugins.d.mts +12 -0
  41. package/dist/assembly/assemblePlugins.mjs +146 -0
  42. package/dist/assembly/databasePlugins.cjs +23 -0
  43. package/dist/assembly/databasePlugins.d.cts +43 -0
  44. package/dist/assembly/databasePlugins.d.mts +43 -0
  45. package/dist/assembly/databasePlugins.mjs +22 -0
  46. package/dist/core/api.cjs +91 -0
  47. package/dist/core/api.d.cts +65 -0
  48. package/dist/core/api.d.mts +65 -0
  49. package/dist/core/api.mjs +87 -0
  50. package/dist/core/baseCandidates.cjs +71 -0
  51. package/dist/core/baseCandidates.d.cts +17 -0
  52. package/dist/core/baseCandidates.d.mts +17 -0
  53. package/dist/core/baseCandidates.mjs +69 -0
  54. package/dist/core/operations.cjs +350 -0
  55. package/dist/core/operations.mjs +350 -0
  56. package/dist/core/reads.cjs +273 -0
  57. package/dist/core/reads.d.cts +48 -0
  58. package/dist/core/reads.d.mts +48 -0
  59. package/dist/core/reads.mjs +267 -0
  60. package/dist/core/releases.cjs +193 -0
  61. package/dist/core/releases.mjs +190 -0
  62. package/dist/core/schema.cjs +279 -0
  63. package/dist/core/schema.d.cts +307 -0
  64. package/dist/core/schema.d.mts +307 -0
  65. package/dist/core/schema.mjs +277 -0
  66. package/dist/core/writes.cjs +96 -0
  67. package/dist/core/writes.mjs +91 -0
  68. package/dist/createHotUpdaterCore.cjs +61 -63
  69. package/dist/createHotUpdaterCore.d.cts +53 -45
  70. package/dist/createHotUpdaterCore.d.mts +53 -45
  71. package/dist/createHotUpdaterCore.mjs +61 -63
  72. package/dist/database/cursor.cjs +44 -0
  73. package/dist/database/cursor.d.cts +7 -0
  74. package/dist/database/cursor.d.mts +7 -0
  75. package/dist/database/cursor.mjs +40 -0
  76. package/dist/database/database.cjs +44 -0
  77. package/dist/database/database.d.cts +123 -0
  78. package/dist/database/database.d.mts +123 -0
  79. package/dist/database/database.mjs +44 -0
  80. package/dist/database/definitions.d.cts +68 -0
  81. package/dist/database/definitions.d.mts +68 -0
  82. package/dist/database/engine.cjs +37 -0
  83. package/dist/database/engine.d.cts +40 -0
  84. package/dist/database/engine.d.mts +40 -0
  85. package/dist/database/engine.mjs +37 -0
  86. package/dist/database/engineAggregates.cjs +115 -0
  87. package/dist/database/engineAggregates.mjs +112 -0
  88. package/dist/database/engineReads.cjs +180 -0
  89. package/dist/database/engineReads.d.cts +35 -0
  90. package/dist/database/engineReads.d.mts +35 -0
  91. package/dist/database/engineReads.mjs +179 -0
  92. package/dist/database/engineTransaction.cjs +403 -0
  93. package/dist/database/engineTransaction.d.cts +26 -0
  94. package/dist/database/engineTransaction.d.mts +26 -0
  95. package/dist/database/engineTransaction.mjs +402 -0
  96. package/dist/database/errors.cjs +27 -0
  97. package/dist/database/errors.d.cts +21 -0
  98. package/dist/database/errors.d.mts +21 -0
  99. package/dist/database/errors.mjs +24 -0
  100. package/dist/database/fence.cjs +124 -0
  101. package/dist/database/fence.d.cts +42 -0
  102. package/dist/database/fence.d.mts +42 -0
  103. package/dist/database/fence.mjs +116 -0
  104. package/dist/database/index.cjs +127 -0
  105. package/dist/database/index.d.cts +17 -0
  106. package/dist/database/index.d.mts +17 -0
  107. package/dist/database/index.mjs +15 -0
  108. package/dist/database/kv/kvAdapter.cjs +273 -0
  109. package/dist/database/kv/kvAdapter.d.cts +101 -0
  110. package/dist/database/kv/kvAdapter.d.mts +101 -0
  111. package/dist/database/kv/kvAdapter.mjs +272 -0
  112. package/dist/database/resolveSchema.cjs +196 -0
  113. package/dist/database/resolveSchema.d.cts +42 -0
  114. package/dist/database/resolveSchema.d.mts +42 -0
  115. package/dist/database/resolveSchema.mjs +193 -0
  116. package/dist/database/schema.cjs +21 -0
  117. package/dist/database/schema.d.cts +61 -0
  118. package/dist/database/schema.d.mts +61 -0
  119. package/dist/database/schema.mjs +20 -0
  120. package/dist/database/sql/sqlAdapter.cjs +282 -0
  121. package/dist/database/sql/sqlAdapter.d.cts +46 -0
  122. package/dist/database/sql/sqlAdapter.d.mts +46 -0
  123. package/dist/database/sql/sqlAdapter.mjs +279 -0
  124. package/dist/database/sql/sqlSchema.cjs +115 -0
  125. package/dist/database/sql/sqlSchema.d.cts +8 -0
  126. package/dist/database/sql/sqlSchema.d.mts +8 -0
  127. package/dist/database/sql/sqlSchema.mjs +111 -0
  128. package/dist/db/builtInDatabase.cjs +104 -0
  129. package/dist/db/builtInDatabase.d.cts +38 -0
  130. package/dist/db/builtInDatabase.d.mts +38 -0
  131. package/dist/db/builtInDatabase.mjs +97 -0
  132. package/dist/db/createBundleDiff.cjs +6 -6
  133. package/dist/db/createBundleDiff.d.cts +4 -7
  134. package/dist/db/createBundleDiff.d.mts +4 -7
  135. package/dist/db/createBundleDiff.mjs +5 -5
  136. package/dist/db/engineDrizzleSchema.cjs +54 -0
  137. package/dist/db/engineDrizzleSchema.mjs +54 -0
  138. package/dist/db/engineMigrator.cjs +53 -0
  139. package/dist/db/engineMigrator.mjs +53 -0
  140. package/dist/db/enginePrismaSchema.cjs +85 -0
  141. package/dist/db/enginePrismaSchema.d.cts +5 -0
  142. package/dist/db/enginePrismaSchema.d.mts +5 -0
  143. package/dist/db/enginePrismaSchema.mjs +84 -0
  144. package/dist/db/engineSql.cjs +26 -0
  145. package/dist/db/engineSql.d.cts +17 -0
  146. package/dist/db/engineSql.d.mts +17 -0
  147. package/dist/db/engineSql.mjs +25 -0
  148. package/dist/db/engineSqlMigrator.cjs +66 -0
  149. package/dist/db/engineSqlMigrator.mjs +66 -0
  150. package/dist/db/fixedMigratorShared.cjs +0 -11
  151. package/dist/db/fixedMigratorShared.mjs +1 -8
  152. package/dist/db/index.cjs +23 -8
  153. package/dist/db/index.d.cts +10 -4
  154. package/dist/db/index.d.mts +10 -4
  155. package/dist/db/index.mjs +16 -8
  156. package/dist/db/releaseCatalog.cjs +20 -44
  157. package/dist/db/releaseCatalog.d.cts +2 -3
  158. package/dist/db/releaseCatalog.d.mts +2 -3
  159. package/dist/db/releaseCatalog.mjs +20 -44
  160. package/dist/db/schemaSettings.cjs +63 -0
  161. package/dist/db/schemaSettings.d.cts +12 -0
  162. package/dist/db/schemaSettings.d.mts +12 -0
  163. package/dist/db/schemaSettings.mjs +62 -0
  164. package/dist/db/settingsMigrator.cjs +92 -0
  165. package/dist/db/settingsMigrator.mjs +89 -0
  166. package/dist/db/types.cjs +3 -12
  167. package/dist/db/types.d.cts +26 -69
  168. package/dist/db/types.d.mts +26 -69
  169. package/dist/db/types.mjs +2 -11
  170. package/dist/db/updateArtifacts.cjs +38 -68
  171. package/dist/db/updateArtifacts.mjs +40 -69
  172. package/dist/handler.cjs +72 -43
  173. package/dist/handler.d.cts +3 -6
  174. package/dist/handler.d.mts +3 -6
  175. package/dist/handler.mjs +73 -43
  176. package/dist/handlerAdminRoutes.cjs +375 -0
  177. package/dist/handlerAdminRoutes.mjs +373 -0
  178. package/dist/handlerParameters.cjs +6 -11
  179. package/dist/handlerParameters.mjs +6 -10
  180. package/dist/handlerReleaseCatalogRoutes.cjs +11 -14
  181. package/dist/handlerReleaseCatalogRoutes.mjs +11 -13
  182. package/dist/handlerTypes.d.cts +2 -56
  183. package/dist/handlerTypes.d.mts +2 -56
  184. package/dist/handlerVersionRoutes.cjs +20 -4
  185. package/dist/handlerVersionRoutes.d.cts +1 -0
  186. package/dist/handlerVersionRoutes.d.mts +1 -0
  187. package/dist/handlerVersionRoutes.mjs +20 -4
  188. package/dist/index.cjs +4 -7
  189. package/dist/index.d.cts +10 -9
  190. package/dist/index.d.mts +10 -9
  191. package/dist/index.mjs +4 -4
  192. package/dist/insights/domain.d.cts +53 -70
  193. package/dist/insights/domain.d.mts +53 -70
  194. package/dist/insights/errors.cjs +35 -8
  195. package/dist/insights/errors.mjs +35 -8
  196. package/dist/insights/eventInput.cjs +64 -24
  197. package/dist/insights/eventInput.mjs +63 -25
  198. package/dist/insights/provider.cjs +356 -0
  199. package/dist/insights/provider.d.cts +6 -0
  200. package/dist/insights/provider.d.mts +6 -0
  201. package/dist/insights/provider.mjs +355 -0
  202. package/dist/insights/queryInput.cjs +78 -43
  203. package/dist/insights/queryInput.mjs +76 -40
  204. package/dist/insights/routes.cjs +94 -34
  205. package/dist/insights/routes.mjs +93 -35
  206. package/dist/insights/types.d.cts +27 -12
  207. package/dist/insights/types.d.mts +27 -12
  208. package/dist/node.d.cts +1 -2
  209. package/dist/node.d.mts +1 -2
  210. package/dist/package.cjs +1 -1
  211. package/dist/package.mjs +1 -1
  212. package/dist/plugins/api-keys/index.cjs +50 -0
  213. package/dist/plugins/api-keys/index.d.cts +85 -0
  214. package/dist/plugins/api-keys/index.d.mts +85 -0
  215. package/dist/plugins/api-keys/index.mjs +47 -0
  216. package/dist/plugins/api-keys/model.cjs +58 -0
  217. package/dist/plugins/api-keys/model.d.cts +8 -0
  218. package/dist/plugins/api-keys/model.d.mts +8 -0
  219. package/dist/plugins/api-keys/model.mjs +58 -0
  220. package/dist/plugins/api-keys/schema.cjs +38 -0
  221. package/dist/plugins/api-keys/schema.d.cts +44 -0
  222. package/dist/plugins/api-keys/schema.d.mts +44 -0
  223. package/dist/plugins/api-keys/schema.mjs +39 -0
  224. package/dist/plugins/builtIn.cjs +7 -0
  225. package/dist/plugins/builtIn.mjs +6 -0
  226. package/dist/plugins/definePlugin.cjs +5 -0
  227. package/dist/plugins/definePlugin.d.cts +73 -0
  228. package/dist/plugins/definePlugin.d.mts +73 -0
  229. package/dist/plugins/definePlugin.mjs +5 -0
  230. package/dist/plugins/index.cjs +17 -0
  231. package/dist/plugins/index.d.cts +9 -0
  232. package/dist/plugins/index.d.mts +9 -0
  233. package/dist/plugins/index.mjs +7 -0
  234. package/dist/plugins/insights/index.cjs +48 -0
  235. package/dist/plugins/insights/index.d.cts +295 -0
  236. package/dist/plugins/insights/index.d.mts +295 -0
  237. package/dist/plugins/insights/index.mjs +44 -0
  238. package/dist/plugins/insights/model.cjs +17 -0
  239. package/dist/plugins/insights/model.d.cts +10 -0
  240. package/dist/plugins/insights/model.d.mts +10 -0
  241. package/dist/plugins/insights/model.mjs +17 -0
  242. package/dist/plugins/insights/reads.cjs +471 -0
  243. package/dist/plugins/insights/reads.mjs +466 -0
  244. package/dist/plugins/insights/recordEvent.cjs +135 -0
  245. package/dist/plugins/insights/recordEvent.d.cts +13 -0
  246. package/dist/plugins/insights/recordEvent.d.mts +13 -0
  247. package/dist/plugins/insights/recordEvent.mjs +132 -0
  248. package/dist/plugins/insights/schema.cjs +347 -0
  249. package/dist/plugins/insights/schema.d.cts +258 -0
  250. package/dist/plugins/insights/schema.d.mts +258 -0
  251. package/dist/plugins/insights/schema.mjs +344 -0
  252. package/dist/storageAccess.cjs +0 -1
  253. package/dist/types/index.d.cts +2 -29
  254. package/dist/types/index.d.mts +2 -29
  255. package/package.json +30 -7
  256. package/src/adapters/drizzle.conformance.integration.spec.ts +34 -0
  257. package/src/adapters/drizzle.readBudgets.integration.spec.ts +41 -0
  258. package/src/adapters/drizzle.spec.ts +277 -208
  259. package/src/adapters/drizzle.ts +48 -128
  260. package/src/adapters/drizzleExecutor.ts +166 -0
  261. package/src/adapters/kysely.conformance.integration.spec.ts +36 -0
  262. package/src/adapters/kysely.readBudgets.integration.spec.ts +42 -0
  263. package/src/adapters/kysely.spec.ts +212 -117
  264. package/src/adapters/kysely.ts +32 -87
  265. package/src/adapters/kyselyExecutor.ts +53 -0
  266. package/src/adapters/mongodb.integration.spec.ts +180 -0
  267. package/src/adapters/mongodb.readBudgets.integration.spec.ts +61 -0
  268. package/src/adapters/mongodb.ts +36 -65
  269. package/src/adapters/mongodbAdapter.ts +293 -0
  270. package/src/adapters/prisma.conformance.integration.spec.ts +36 -0
  271. package/src/adapters/prisma.integration.spec.ts +138 -0
  272. package/src/adapters/prisma.readBudgets.integration.spec.ts +40 -0
  273. package/src/adapters/prisma.spec.ts +226 -173
  274. package/src/adapters/prisma.ts +60 -451
  275. package/src/adapters/prismaExecutor.ts +107 -0
  276. package/src/adapters/prismaTestClients.ts +175 -0
  277. package/src/adapters/sqlProviders.ts +14 -0
  278. package/src/apiKeys.integration.spec.ts +19 -119
  279. package/src/apiKeys.spec.ts +39 -35
  280. package/src/apiKeys.ts +2 -8
  281. package/src/assembly/assemblePlugins.ts +269 -0
  282. package/src/assembly/assembly.spec.ts +325 -0
  283. package/src/assembly/assembly.types.spec.ts +155 -0
  284. package/src/assembly/builtInRoutes.spec.ts +213 -0
  285. package/src/assembly/databasePlugins.spec.ts +71 -0
  286. package/src/assembly/databasePlugins.ts +96 -0
  287. package/src/core/api.ts +139 -0
  288. package/src/core/baseCandidates.spec.ts +378 -0
  289. package/src/core/baseCandidates.ts +136 -0
  290. package/src/core/index.ts +44 -0
  291. package/src/core/operations.spec.ts +415 -0
  292. package/src/core/operations.ts +551 -0
  293. package/src/core/reads.spec.ts +300 -0
  294. package/src/core/reads.ts +417 -0
  295. package/src/core/releases.spec.ts +308 -0
  296. package/src/core/releases.ts +345 -0
  297. package/src/core/schema.ts +173 -0
  298. package/src/core/writes.ts +160 -0
  299. package/src/createHotUpdaterCore.ts +191 -167
  300. package/src/database/cursor.ts +65 -0
  301. package/src/database/database.ts +335 -0
  302. package/src/database/database.types.spec.ts +135 -0
  303. package/src/database/definitions.ts +72 -0
  304. package/src/database/engine.ts +62 -0
  305. package/src/database/engineAggregates.spec.ts +539 -0
  306. package/src/database/engineAggregates.ts +193 -0
  307. package/src/database/engineReads.spec.ts +219 -0
  308. package/src/database/engineReads.ts +302 -0
  309. package/src/database/engineTransaction.spec.ts +710 -0
  310. package/src/database/engineTransaction.ts +588 -0
  311. package/src/database/errors.ts +30 -0
  312. package/src/database/fence.spec.ts +223 -0
  313. package/src/database/fence.ts +171 -0
  314. package/src/database/index.ts +154 -0
  315. package/src/database/kv/kvAdapter.conformance.integration.spec.ts +17 -0
  316. package/src/database/kv/kvAdapter.readBudgets.integration.spec.ts +17 -0
  317. package/src/database/kv/kvAdapter.spec.ts +468 -0
  318. package/src/database/kv/kvAdapter.ts +450 -0
  319. package/src/database/kv/kvTestStore.ts +91 -0
  320. package/src/database/memory.readBudgets.integration.spec.ts +13 -0
  321. package/src/database/resolveSchema.spec.ts +230 -0
  322. package/src/database/resolveSchema.ts +372 -0
  323. package/src/database/schema.ts +169 -0
  324. package/src/database/schema.types.spec.ts +94 -0
  325. package/src/database/sql/docker-compose.yml +36 -0
  326. package/src/database/sql/sqlAdapter.integration.spec.ts +148 -0
  327. package/src/database/sql/sqlAdapter.readBudgets.integration.spec.ts +109 -0
  328. package/src/database/sql/sqlAdapter.spec.ts +255 -0
  329. package/src/database/sql/sqlAdapter.ts +532 -0
  330. package/src/database/sql/sqlSchema.ts +205 -0
  331. package/src/database/sql/sqlTestExecutors.ts +183 -0
  332. package/src/databaseTestSuite.spec.ts +39 -0
  333. package/src/db/builtInDatabase.ts +149 -0
  334. package/src/db/bundleRows.spec.ts +3 -3
  335. package/src/db/createBundleDiff.spec.ts +43 -29
  336. package/src/db/createBundleDiff.ts +13 -7
  337. package/src/db/engineDrizzleSchema.ts +72 -0
  338. package/src/db/engineMigrator.ts +105 -0
  339. package/src/db/enginePrismaSchema.ts +147 -0
  340. package/src/db/engineSql.spec.ts +129 -0
  341. package/src/db/engineSql.ts +48 -0
  342. package/src/db/engineSqlMigrator.ts +116 -0
  343. package/src/db/fixedMigratorShared.ts +1 -20
  344. package/src/db/index.spec.ts +116 -824
  345. package/src/db/index.ts +43 -14
  346. package/src/db/pluginTables.spec.ts +218 -0
  347. package/src/db/releaseCatalog.ts +48 -90
  348. package/src/db/schemaSettings.ts +104 -0
  349. package/src/db/settingsMigrator.spec.ts +65 -0
  350. package/src/db/settingsMigrator.ts +152 -0
  351. package/src/db/types.ts +25 -165
  352. package/src/db/updateArtifacts.spec.ts +170 -294
  353. package/src/db/updateArtifacts.ts +74 -142
  354. package/src/db/updateCheck.bench.ts +47 -0
  355. package/src/handler-standalone.integration.spec.ts +204 -412
  356. package/src/handler.spec.ts +134 -51
  357. package/src/handler.testFixtures.ts +14 -19
  358. package/src/handler.ts +163 -75
  359. package/src/handlerAdminRoutes.spec.ts +183 -0
  360. package/src/handlerAdminRoutes.ts +536 -0
  361. package/src/handlerAuth.integration.spec.ts +3 -3
  362. package/src/handlerManagement.spec.ts +136 -196
  363. package/src/handlerReleaseCatalogRoutes.ts +15 -17
  364. package/src/handlerTypes.ts +3 -80
  365. package/src/handlerVersionRoutes.ts +20 -7
  366. package/src/index.ts +7 -14
  367. package/src/insights/domain.ts +56 -77
  368. package/src/insights/errors.spec.ts +48 -0
  369. package/src/insights/errors.ts +50 -6
  370. package/src/insights/eventInput.ts +80 -27
  371. package/src/insights/insights.integration.spec.ts +525 -44
  372. package/src/insights/provider.spec.ts +574 -0
  373. package/src/insights/provider.ts +667 -0
  374. package/src/insights/queryInput.ts +113 -73
  375. package/src/insights/routes.ts +125 -69
  376. package/src/insights/types.ts +47 -36
  377. package/src/lintRules.spec.ts +76 -0
  378. package/src/plugins/api-keys/apiKeysPlugin.spec.ts +172 -0
  379. package/src/plugins/api-keys/index.ts +66 -0
  380. package/src/plugins/api-keys/model.ts +69 -0
  381. package/src/plugins/api-keys/schema.ts +22 -0
  382. package/src/plugins/builtIn.ts +5 -0
  383. package/src/plugins/definePlugin.ts +100 -0
  384. package/src/plugins/index.ts +55 -0
  385. package/src/plugins/insights/index.ts +86 -0
  386. package/src/plugins/insights/insightsRollout.integration.spec.ts +187 -0
  387. package/src/plugins/insights/model.spec.ts +66 -0
  388. package/src/plugins/insights/model.ts +19 -0
  389. package/src/plugins/insights/reads.spec.ts +725 -0
  390. package/src/plugins/insights/reads.ts +707 -0
  391. package/src/plugins/insights/recordEvent.spec.ts +443 -0
  392. package/src/plugins/insights/recordEvent.ts +238 -0
  393. package/src/plugins/insights/schema.ts +229 -0
  394. package/src/plugins/pluginTestHarness.spec.ts +56 -0
  395. package/src/readBudgets.testFixtures.ts +15 -0
  396. package/src/releaseCatalogRoutes.integration.spec.ts +47 -92
  397. package/src/runtime.spec.ts +91 -77
  398. package/src/runtime.testFixtures.ts +28 -44
  399. package/src/runtimeBundles.integration.spec.ts +112 -0
  400. package/src/testUtilsMutation.integration.spec.ts +215 -0
  401. package/src/testUtilsPackage.integration.spec.ts +176 -0
  402. package/src/types/index.ts +0 -32
  403. package/dist/adapters/databaseConstraintErrors.cjs +0 -23
  404. package/dist/adapters/databaseConstraintErrors.mjs +0 -21
  405. package/dist/adapters/databasePluginUtils.cjs +0 -117
  406. package/dist/adapters/databasePluginUtils.mjs +0 -106
  407. package/dist/adapters/drizzleCrud.cjs +0 -250
  408. package/dist/adapters/drizzleCrud.mjs +0 -249
  409. package/dist/adapters/drizzleLazyDB.cjs +0 -101
  410. package/dist/adapters/drizzleLazyDB.mjs +0 -101
  411. package/dist/adapters/drizzleQuery.cjs +0 -68
  412. package/dist/adapters/drizzleQuery.mjs +0 -67
  413. package/dist/adapters/kyselyCrud.cjs +0 -254
  414. package/dist/adapters/kyselyCrud.mjs +0 -253
  415. package/dist/adapters/kyselyQuery.cjs +0 -56
  416. package/dist/adapters/kyselyQuery.mjs +0 -55
  417. package/dist/adapters/mongodbCollections.cjs +0 -36
  418. package/dist/adapters/mongodbCollections.mjs +0 -30
  419. package/dist/adapters/mongodbQuery.cjs +0 -77
  420. package/dist/adapters/mongodbQuery.mjs +0 -70
  421. package/dist/adapters/mongodbReads.cjs +0 -148
  422. package/dist/adapters/mongodbReads.mjs +0 -147
  423. package/dist/adapters/mongodbWrites.cjs +0 -134
  424. package/dist/adapters/mongodbWrites.mjs +0 -133
  425. package/dist/adapters/prismaQuery.cjs +0 -58
  426. package/dist/adapters/prismaQuery.mjs +0 -56
  427. package/dist/adapters/prismaRows.cjs +0 -198
  428. package/dist/adapters/prismaRows.mjs +0 -188
  429. package/dist/db/databasePluginCore.cjs +0 -138
  430. package/dist/db/databasePluginCore.mjs +0 -137
  431. package/dist/db/fixedMigrator.cjs +0 -79
  432. package/dist/db/fixedMigrator.mjs +0 -78
  433. package/dist/db/fixedMigratorMongo.cjs +0 -319
  434. package/dist/db/fixedMigratorMongo.mjs +0 -319
  435. package/dist/db/mongoMigrationExecution.cjs +0 -11
  436. package/dist/db/mongoMigrationExecution.mjs +0 -11
  437. package/dist/db/schema/mongodb.cjs +0 -25
  438. package/dist/db/schema/mongodb.mjs +0 -25
  439. package/dist/db/schema/registry.cjs +0 -21
  440. package/dist/db/schema/registry.mjs +0 -17
  441. package/dist/db/schema/sql.cjs +0 -101
  442. package/dist/db/schema/sql.mjs +0 -97
  443. package/dist/db/schema/sqlOperations.cjs +0 -27
  444. package/dist/db/schema/sqlOperations.mjs +0 -26
  445. package/dist/db/schemaGenerators.cjs +0 -256
  446. package/dist/db/schemaGenerators.mjs +0 -254
  447. package/dist/db/schemaReadiness.cjs +0 -24
  448. package/dist/db/schemaReadiness.d.cts +0 -8
  449. package/dist/db/schemaReadiness.d.mts +0 -8
  450. package/dist/db/schemaReadiness.mjs +0 -23
  451. package/dist/db/sqlMigrationExecution.cjs +0 -67
  452. package/dist/db/sqlMigrationExecution.mjs +0 -66
  453. package/dist/handlerBundleRoutes.cjs +0 -155
  454. package/dist/handlerBundleRoutes.mjs +0 -155
  455. package/dist/handlerReleaseManagementRoutes.cjs +0 -125
  456. package/dist/handlerReleaseManagementRoutes.mjs +0 -124
  457. package/dist/insights/bounded/activeOverview.cjs +0 -87
  458. package/dist/insights/bounded/activeOverview.mjs +0 -85
  459. package/dist/insights/bounded/installationSearch.cjs +0 -42
  460. package/dist/insights/bounded/installationSearch.mjs +0 -42
  461. package/dist/insights/bounded/persistence.cjs +0 -39
  462. package/dist/insights/bounded/persistence.mjs +0 -38
  463. package/dist/insights/bounded/provider.cjs +0 -170
  464. package/dist/insights/bounded/provider.d.cts +0 -7
  465. package/dist/insights/bounded/provider.d.mts +0 -7
  466. package/dist/insights/bounded/provider.mjs +0 -170
  467. package/dist/insights/bounded/scan.cjs +0 -144
  468. package/dist/insights/bounded/scan.mjs +0 -138
  469. package/dist/insights/persistence.d.cts +0 -6
  470. package/dist/insights/persistence.d.mts +0 -6
  471. package/dist/schema/dsl.cjs +0 -103
  472. package/dist/schema/dsl.mjs +0 -87
  473. package/dist/schema/index.cjs +0 -6
  474. package/dist/schema/index.mjs +0 -7
  475. package/dist/schema/settings.cjs +0 -9
  476. package/dist/schema/settings.mjs +0 -9
  477. package/dist/schema/types.cjs +0 -8
  478. package/dist/schema/types.mjs +0 -6
  479. package/dist/schema/v1_0_0.cjs +0 -364
  480. package/dist/schema/v1_0_0.mjs +0 -357
  481. package/src/adapters/databaseConstraintErrors.ts +0 -25
  482. package/src/adapters/databasePluginTestDatabase.ts +0 -106
  483. package/src/adapters/databasePluginUtils.spec.ts +0 -29
  484. package/src/adapters/databasePluginUtils.ts +0 -214
  485. package/src/adapters/drizzleCrud.ts +0 -419
  486. package/src/adapters/drizzleLazyDB.ts +0 -257
  487. package/src/adapters/drizzleQuery.ts +0 -164
  488. package/src/adapters/kyselyCrud.ts +0 -588
  489. package/src/adapters/kyselyQuery.ts +0 -128
  490. package/src/adapters/mongodb.spec.ts +0 -141
  491. package/src/adapters/mongodbCollections.ts +0 -62
  492. package/src/adapters/mongodbQuery.ts +0 -226
  493. package/src/adapters/mongodbReads.ts +0 -311
  494. package/src/adapters/mongodbRows.spec.ts +0 -64
  495. package/src/adapters/mongodbRows.ts +0 -118
  496. package/src/adapters/mongodbTestClient.ts +0 -342
  497. package/src/adapters/mongodbTestFilter.ts +0 -166
  498. package/src/adapters/mongodbWrites.ts +0 -260
  499. package/src/adapters/prismaQuery.ts +0 -129
  500. package/src/adapters/prismaRows.spec.ts +0 -98
  501. package/src/adapters/prismaRows.ts +0 -301
  502. package/src/adapters/prismaTestClient.ts +0 -396
  503. package/src/calculatePagination.ts +0 -34
  504. package/src/db/databasePluginCore.spec.ts +0 -62
  505. package/src/db/databasePluginCore.testFixtures.ts +0 -76
  506. package/src/db/databasePluginCore.ts +0 -185
  507. package/src/db/databasePluginUpdateCheck.bench.ts +0 -107
  508. package/src/db/fixedMigrator.spec.ts +0 -231
  509. package/src/db/fixedMigrator.ts +0 -147
  510. package/src/db/fixedMigratorMongo.spec.ts +0 -192
  511. package/src/db/fixedMigratorMongo.ts +0 -425
  512. package/src/db/hotUpdaterSchema.ts +0 -5
  513. package/src/db/mongoMigrationExecution.ts +0 -23
  514. package/src/db/schema/definitions.ts +0 -1
  515. package/src/db/schema/mongodb.ts +0 -40
  516. package/src/db/schema/registry.ts +0 -55
  517. package/src/db/schema/sql.ts +0 -241
  518. package/src/db/schema/sqlOperations.ts +0 -63
  519. package/src/db/schema/types.ts +0 -1
  520. package/src/db/schemaGenerators.ts +0 -466
  521. package/src/db/schemaReadiness.ts +0 -34
  522. package/src/db/sqlMigrationExecution.spec.ts +0 -65
  523. package/src/db/sqlMigrationExecution.ts +0 -108
  524. package/src/db/types.spec.ts +0 -55
  525. package/src/handlerBundleRoutes.ts +0 -259
  526. package/src/handlerReleaseManagementRoutes.ts +0 -213
  527. package/src/insights/bounded/activeOverview.spec.ts +0 -189
  528. package/src/insights/bounded/activeOverview.ts +0 -148
  529. package/src/insights/bounded/installationSearch.spec.ts +0 -130
  530. package/src/insights/bounded/installationSearch.ts +0 -69
  531. package/src/insights/bounded/persistence.ts +0 -43
  532. package/src/insights/bounded/provider.spec.ts +0 -219
  533. package/src/insights/bounded/provider.ts +0 -229
  534. package/src/insights/bounded/scan.ts +0 -235
  535. package/src/insights/persistence.ts +0 -10
  536. package/src/schema/dsl-all-versions.spec.ts +0 -35
  537. package/src/schema/dsl.ts +0 -187
  538. package/src/schema/index.ts +0 -10
  539. package/src/schema/settings.ts +0 -15
  540. package/src/schema/types.ts +0 -79
  541. package/src/schema/v1_0_0.spec.ts +0 -146
  542. package/src/schema/v1_0_0.ts +0 -465
@@ -0,0 +1,466 @@
1
+ import "../../insights/provider.mjs";
2
+ import { DAILY_EVENTS, DAY_MS, HOUR_MS } from "./schema.mjs";
3
+ import { PAIR_FIELD, bundlePairKey, insightsIdentity } from "./recordEvent.mjs";
4
+ import { DatabasePluginInputError } from "@hot-updater/plugin-core";
5
+ import { countInsightsDistinct, mergeInsightsDistinct } from "@hot-updater/plugin-core/internal";
6
+ //#region src/plugins/insights/reads.ts
7
+ const PAGE = 500;
8
+ const hourFloor = (ms) => ms - ms % HOUR_MS;
9
+ const hourCeil = (ms) => hourFloor(ms + HOUR_MS - 1);
10
+ const dayFloor = (ms) => ms - ms % DAY_MS;
11
+ const dayCeil = (ms) => dayFloor(ms + DAY_MS - 1);
12
+ /** Every page of one read, in order. */
13
+ const drain = async (read) => {
14
+ const rows = [];
15
+ let cursor;
16
+ do {
17
+ const page = await read(cursor === void 0 ? {} : { cursor });
18
+ rows.push(...page.rows);
19
+ cursor = page.next;
20
+ } while (cursor !== void 0);
21
+ return rows;
22
+ };
23
+ const EVENT_FIELDS = [
24
+ "id",
25
+ "type",
26
+ "install_id",
27
+ "user_id",
28
+ "from_release_id",
29
+ "from_bundle_id",
30
+ "to_release_id",
31
+ "to_bundle_id",
32
+ "platform",
33
+ "app_version",
34
+ "channel",
35
+ "metadata",
36
+ "received_at_ms"
37
+ ];
38
+ /** A stored event or head, as the event row it holds. */
39
+ const toEvent = (row) => Object.fromEntries(EVENT_FIELDS.map((field) => [field, row[field]]));
40
+ const bundleRef = (filter) => filter.type === "RECOVERED" ? `from:${filter.fromBundleId}` : `to:${filter.toBundleId}`;
41
+ const scopeOf = (filter) => ({
42
+ platform: filter.platform,
43
+ channel: filter.channel,
44
+ type: filter.type,
45
+ bundle_ref: bundleRef(filter)
46
+ });
47
+ /** One UTC day of a global or bundle list, newest first. */
48
+ const eventsOfDay = (db, filter, day, range, limit) => filter.kind === "all" ? db.findMany("bundle_events", {
49
+ index: "byDay",
50
+ where: { day },
51
+ range,
52
+ order: "desc",
53
+ limit
54
+ }) : db.findMany("bundle_events", {
55
+ index: "byBundle",
56
+ where: {
57
+ ...scopeOf(filter),
58
+ day
59
+ },
60
+ range,
61
+ order: "desc",
62
+ limit
63
+ });
64
+ /**
65
+ * The newest UTC day before `day`, and not before `since`'s, that holds an
66
+ * event the list matches, from one outcome row: the global list's per-day
67
+ * count, or the bundle filter's own hourly one.
68
+ */
69
+ const newestDayBelow = async (db, filter, day, since) => {
70
+ const counted = filter.kind === "all" ? {
71
+ where: DAILY_EVENTS,
72
+ from: dayFloor(since)
73
+ } : {
74
+ where: scopeOf(filter),
75
+ from: hourFloor(since)
76
+ };
77
+ const [newest] = (await db.findAggregates("insights_outcomes", {
78
+ index: "byRef",
79
+ where: counted.where,
80
+ range: {
81
+ gte: counted.from,
82
+ lt: day
83
+ },
84
+ order: "desc",
85
+ limit: 1
86
+ })).rows;
87
+ return newest === void 0 ? void 0 : dayFloor(newest.bucket_start_ms);
88
+ };
89
+ /**
90
+ * Newest first over [since, before), after the cursor. The global and bundle
91
+ * lists cover at most 90 × 24 hours, however many UTC days that touches, and
92
+ * reject a longer range instead of cutting it short. They read one query per
93
+ * UTC day that holds a matching event: a day that holds none is read once,
94
+ * then one outcome row names the newest day below it that does, so a gap of
95
+ * any length costs two reads.
96
+ */
97
+ const listEvents = async (db, input) => {
98
+ const since = input.sinceMs ?? 0;
99
+ const range = {
100
+ gte: since,
101
+ lt: input.after === void 0 ? input.beforeReceivedAtMs : [input.after.receivedAtMs, input.after.id]
102
+ };
103
+ const { filter, limit } = input;
104
+ if (filter.kind === "installationMovement") return (await db.findMany("bundle_events", {
105
+ index: "movementsByInstall",
106
+ where: { movement_install_id: filter.installId },
107
+ range,
108
+ order: "desc",
109
+ limit
110
+ })).rows.map(toEvent);
111
+ if (input.beforeReceivedAtMs - since > 7776e6) throw new DatabasePluginInputError("invalid-query");
112
+ const rows = [];
113
+ const bottom = dayFloor(since);
114
+ let day = dayFloor(input.after?.receivedAtMs ?? input.beforeReceivedAtMs - 1);
115
+ while (day !== void 0 && day >= bottom && rows.length < limit) {
116
+ const page = await eventsOfDay(db, filter, day, range, limit - rows.length);
117
+ rows.push(...page.rows.map(toEvent));
118
+ day = page.rows.length > 0 ? day - DAY_MS : day > bottom ? await newestDayBelow(db, filter, day, since) : void 0;
119
+ }
120
+ return rows;
121
+ };
122
+ /** One point read for an installation; a user's installations in binary install id order. */
123
+ const findLatestEvents = async (db, input) => {
124
+ if ("installId" in input) {
125
+ const head = await db.findOne("bundle_event_heads", { install_id: input.installId });
126
+ return head === null ? [] : [toEvent(head)];
127
+ }
128
+ return (await db.findMany("bundle_event_heads", {
129
+ index: "byUser",
130
+ where: { user_id: input.userId },
131
+ ...input.afterInstallId === void 0 ? {} : { range: { gt: input.afterInstallId } },
132
+ order: "asc",
133
+ limit: input.limit
134
+ })).rows.map(toEvent);
135
+ };
136
+ /** Raw events of one bundle filter over [from, to), which spans at most two partial hours. */
137
+ const countRaw = async (db, filter, from, to) => {
138
+ let total = 0;
139
+ for (let day = dayFloor(from); from < to && day < to; day += DAY_MS) {
140
+ const rows = await drain((page) => db.findMany("bundle_events", {
141
+ index: "byBundle",
142
+ where: {
143
+ ...scopeOf(filter),
144
+ day
145
+ },
146
+ range: {
147
+ gte: from,
148
+ lt: to
149
+ },
150
+ limit: PAGE,
151
+ ...page
152
+ }));
153
+ total += rows.length;
154
+ }
155
+ return total;
156
+ };
157
+ /** Whole hours from outcome counters; the partial hours at either edge from raw events. */
158
+ const countEvents = async (db, input) => {
159
+ const { filter, sinceMs, beforeReceivedAtMs } = input;
160
+ const start = hourCeil(sinceMs);
161
+ const end = hourFloor(beforeReceivedAtMs);
162
+ if (start >= end) return countRaw(db, filter, sinceMs, beforeReceivedAtMs);
163
+ const hours = await drain((page) => db.findAggregates("insights_outcomes", {
164
+ index: "byRef",
165
+ where: scopeOf(filter),
166
+ range: {
167
+ gte: start,
168
+ lt: end
169
+ },
170
+ limit: PAGE,
171
+ ...page
172
+ }));
173
+ return await countRaw(db, filter, sinceMs, start) + hours.reduce((sum, row) => sum + row.events, 0) + await countRaw(db, filter, end, beforeReceivedAtMs);
174
+ };
175
+ /** A bundle filter's distinct (field, value, type) predicates. */
176
+ const latestPredicates = (bundle) => {
177
+ if (bundle === void 0) return void 0;
178
+ return [...new Map(bundle.flatMap(({ field, value, types }) => types.map((type) => [JSON.stringify([
179
+ field,
180
+ value,
181
+ type
182
+ ]), {
183
+ field,
184
+ value,
185
+ type
186
+ }]))).values()];
187
+ };
188
+ /** Heads whose latest event falls in [sinceMs, end), a partial hour: those events' installs, then their heads. */
189
+ const countPartialHeads = async (db, input, predicates, end) => {
190
+ const events = await drain((page) => db.findMany("bundle_events", {
191
+ index: "recent",
192
+ where: {
193
+ channel: input.channel,
194
+ platform: input.platform,
195
+ day: dayFloor(input.sinceMs)
196
+ },
197
+ range: {
198
+ gte: input.sinceMs,
199
+ lt: end
200
+ },
201
+ limit: PAGE,
202
+ ...page
203
+ }));
204
+ const ids = new Set(events.map(({ id }) => id));
205
+ return (await Promise.all([...new Set(events.map(({ install_id }) => install_id))].map((install) => db.findOne("bundle_event_heads", { install_id: install })))).filter((head) => head !== null && ids.has(head.id) && (predicates === void 0 || predicates.some(({ field, value, type }) => head[field] === value && head.type === type))).length;
206
+ };
207
+ /** Latest events at or after `sinceMs`: whole hours from gauges, the first partial hour from heads. */
208
+ const countLatestEvents = async (db, input) => {
209
+ const { platform, channel, sinceMs } = input;
210
+ const start = hourCeil(sinceMs);
211
+ const predicates = latestPredicates(input.bundle);
212
+ let total = 0;
213
+ if (predicates === void 0) {
214
+ const rows = await drain((page) => db.findAggregates("insights_distribution", {
215
+ index: "byScope",
216
+ where: {
217
+ channel,
218
+ platform
219
+ },
220
+ range: { gte: start },
221
+ limit: PAGE,
222
+ ...page
223
+ }));
224
+ total += rows.reduce((sum, row) => sum + row.latest_installations, 0);
225
+ } else {
226
+ const gauge = async (bundleField, bundleId, type) => {
227
+ return (await drain((page) => db.findAggregates("insights_latest_by_bundle", {
228
+ index: "byBundle",
229
+ where: {
230
+ platform,
231
+ channel,
232
+ bundle_field: bundleField,
233
+ bundle_id: bundleId,
234
+ type
235
+ },
236
+ range: { gte: start },
237
+ limit: PAGE,
238
+ ...page
239
+ }))).reduce((sum, row) => sum + row.installations, 0);
240
+ };
241
+ for (const { field, value, type } of predicates) total += await gauge(field, value, type);
242
+ for (const from of predicates) {
243
+ if (from.field !== "from_bundle_id") continue;
244
+ for (const to of predicates) {
245
+ if (to.field !== "to_bundle_id" || to.type !== from.type) continue;
246
+ total -= await gauge(PAIR_FIELD, bundlePairKey(from.value, to.value), from.type);
247
+ }
248
+ }
249
+ }
250
+ return sinceMs < start ? total + await countPartialHeads(db, input, predicates, start) : total;
251
+ };
252
+ /** Periods covering [start, end): whole UTC days when `days` and the window is over 48 hours, hours elsewhere. */
253
+ const periodsOf = (range, days) => {
254
+ const { start, end } = range;
255
+ if (!days || end - start <= 1728e5) return [{
256
+ periodKind: "hour",
257
+ start,
258
+ end
259
+ }];
260
+ const first = Math.min(end, dayCeil(start));
261
+ const last = Math.max(first, dayFloor(end));
262
+ return [
263
+ {
264
+ periodKind: "hour",
265
+ start,
266
+ end: first
267
+ },
268
+ {
269
+ periodKind: "day",
270
+ start: first,
271
+ end: last
272
+ },
273
+ {
274
+ periodKind: "hour",
275
+ start: last,
276
+ end
277
+ }
278
+ ].filter((period) => period.start < period.end);
279
+ };
280
+ /** Every overview or sketch row of one identity over [start, end), mixing day and hour periods. */
281
+ const windowRows = async (db, model, parts, range, days) => {
282
+ const rows = [];
283
+ for (const period of periodsOf(range, days)) {
284
+ const identity = insightsIdentity({
285
+ ...parts,
286
+ periodKind: period.periodKind
287
+ });
288
+ rows.push(...await drain((page) => db.findAggregates(model, {
289
+ index: "window",
290
+ where: { identity },
291
+ range: {
292
+ gte: period.start,
293
+ lt: period.end
294
+ },
295
+ limit: PAGE,
296
+ ...page
297
+ })));
298
+ }
299
+ return rows;
300
+ };
301
+ const counterRows = (...args) => windowRows(args[0], "insights_overview", args[1], args[2], args[3]);
302
+ const sketchRows = (...args) => windowRows(args[0], "insights_sketches", args[1], args[2], args[3]);
303
+ const releaseParts = (release) => ({
304
+ scopeKind: "release",
305
+ releaseKind: "specific",
306
+ releaseId: release.releaseId,
307
+ channel: release.channel,
308
+ platform: release.platform,
309
+ appVersionKind: "all",
310
+ appVersion: ""
311
+ });
312
+ /** A release's lifetime counters: one logical row at bucket 0. */
313
+ const lifetimeMetrics = async (db, release) => {
314
+ const identity = insightsIdentity({
315
+ ...releaseParts(release),
316
+ periodKind: "lifetime"
317
+ });
318
+ const [lifetime] = (await db.findAggregates("insights_overview", {
319
+ index: "window",
320
+ where: { identity },
321
+ range: {
322
+ gte: 0,
323
+ lte: 0
324
+ },
325
+ limit: PAGE
326
+ })).rows;
327
+ return {
328
+ downloads: lifetime?.downloads ?? 0,
329
+ launches: lifetime?.launches ?? 0,
330
+ failedLaunches: lifetime?.failed_launches ?? 0
331
+ };
332
+ };
333
+ /** Counters, unique users, and a per-UTC-day series over a window. */
334
+ const rangedMetrics = async (db, parts, range, days) => {
335
+ const [counters, sketches] = await Promise.all([counterRows(db, parts, range, days), sketchRows(db, parts, range, days)]);
336
+ const series = /* @__PURE__ */ new Map();
337
+ for (const row of counters) {
338
+ const day = dayFloor(row.bucket_start_ms);
339
+ const point = series.get(day) ?? {
340
+ launches: 0,
341
+ failedLaunches: 0
342
+ };
343
+ point.launches += row.launches;
344
+ point.failedLaunches += row.failed_launches;
345
+ series.set(day, point);
346
+ }
347
+ const total = (field) => counters.reduce((sum, row) => sum + row[field], 0);
348
+ return {
349
+ downloads: total("downloads"),
350
+ launches: total("launches"),
351
+ failedLaunches: total("failed_launches"),
352
+ uniqueUsers: countInsightsDistinct(mergeInsightsDistinct(sketches.map((row) => row.launch_users))),
353
+ series: [...series].sort(([left], [right]) => left - right).map(([startMs, point]) => ({
354
+ startMs,
355
+ ...point
356
+ }))
357
+ };
358
+ };
359
+ const getReleaseActivity = async (db, input, now) => {
360
+ return {
361
+ coverage: {
362
+ kind: "complete",
363
+ sinceMs: 0
364
+ },
365
+ data: input.scope !== void 0 ? [{
366
+ scope: input.scope,
367
+ metrics: await rangedMetrics(db, {
368
+ scopeKind: "channel",
369
+ releaseKind: "all",
370
+ releaseId: "",
371
+ channel: input.scope.channel,
372
+ platform: input.scope.platform,
373
+ appVersionKind: "all",
374
+ appVersion: ""
375
+ }, input.timeRange, true)
376
+ }] : await Promise.all(input.releases.map(async (release) => ({
377
+ release,
378
+ metrics: input.timeRange === void 0 ? await lifetimeMetrics(db, release) : await rangedMetrics(db, releaseParts(release), input.timeRange, false)
379
+ }))),
380
+ measuredAtMs: now()
381
+ };
382
+ };
383
+ const byInstallations = (values) => [...values].map(([name, installations]) => ({
384
+ name,
385
+ installations
386
+ })).sort((left, right) => right.installations - left.installations || left.name.localeCompare(right.name, "en", { numeric: true }));
387
+ const getAppUsage = async (db, input, now) => {
388
+ const { timeRange, intervalMs } = input;
389
+ const usage = await sketchRows(db, {
390
+ scopeKind: "usage",
391
+ releaseKind: "all",
392
+ releaseId: "",
393
+ channel: input.channel,
394
+ platform: input.platform,
395
+ appVersionKind: input.appVersion === void 0 ? "all" : "specific",
396
+ appVersion: input.appVersion ?? ""
397
+ }, timeRange, intervalMs % 864e5 === 0 && timeRange.start % 864e5 === 0);
398
+ const distribution = [];
399
+ for (const platform of input.platform === "all" ? ["ios", "android"] : [input.platform]) distribution.push(...await drain((page) => input.appVersion === void 0 ? db.findAggregates("insights_distribution", {
400
+ index: "byScope",
401
+ where: {
402
+ channel: input.channel,
403
+ platform
404
+ },
405
+ range: {
406
+ gte: timeRange.start,
407
+ lt: timeRange.end
408
+ },
409
+ limit: PAGE,
410
+ ...page
411
+ }) : db.findAggregates("insights_distribution", {
412
+ index: "byVersion",
413
+ where: {
414
+ channel: input.channel,
415
+ platform,
416
+ app_version: input.appVersion
417
+ },
418
+ range: {
419
+ gte: timeRange.start,
420
+ lt: timeRange.end
421
+ },
422
+ limit: PAGE,
423
+ ...page
424
+ })));
425
+ const points = [];
426
+ for (let start = timeRange.start; start < timeRange.end; start += intervalMs) points.push({
427
+ startMs: start,
428
+ installations: countInsightsDistinct(mergeInsightsDistinct(usage.filter((row) => row.bucket_start_ms >= start && row.bucket_start_ms < start + intervalMs).map((row) => row.activity_users)))
429
+ });
430
+ const versions = /* @__PURE__ */ new Map();
431
+ const platforms = /* @__PURE__ */ new Map();
432
+ const bundles = /* @__PURE__ */ new Map();
433
+ for (const row of distribution) {
434
+ const count = row.latest_installations;
435
+ versions.set(row.app_version, (versions.get(row.app_version) ?? 0) + count);
436
+ platforms.set(row.platform, (platforms.get(row.platform) ?? 0) + count);
437
+ const releaseId = row.release_id === "" ? null : row.release_id;
438
+ const key = JSON.stringify([
439
+ row.app_version,
440
+ row.platform,
441
+ releaseId
442
+ ]);
443
+ bundles.set(key, {
444
+ appVersion: row.app_version,
445
+ platform: row.platform,
446
+ releaseId,
447
+ installations: (bundles.get(key)?.installations ?? 0) + count
448
+ });
449
+ }
450
+ const sortedVersions = byInstallations(versions);
451
+ return {
452
+ coverage: {
453
+ kind: "complete",
454
+ sinceMs: 0
455
+ },
456
+ activeInstallations: countInsightsDistinct(mergeInsightsDistinct(usage.map((row) => row.activity_users))),
457
+ points,
458
+ appVersions: sortedVersions.map(({ name }) => name),
459
+ versions: sortedVersions,
460
+ platforms: byInstallations(platforms),
461
+ bundleDistribution: [...bundles.values()],
462
+ measuredAtMs: now()
463
+ };
464
+ };
465
+ //#endregion
466
+ export { countEvents, countLatestEvents, findLatestEvents, getAppUsage, getReleaseActivity, listEvents };
@@ -0,0 +1,135 @@
1
+ const require_schema = require("./schema.cjs");
2
+ let _hot_updater_plugin_core_internal = require("@hot-updater/plugin-core/internal");
3
+ //#region src/plugins/insights/recordEvent.ts
4
+ const hourOf = (ms) => ms - ms % require_schema.HOUR_MS;
5
+ const dayOf = (ms) => ms - ms % require_schema.DAY_MS;
6
+ /** The `identity` of an overview or sketch row: its scope and period, hashed. */
7
+ const insightsIdentity = (identity) => (0, _hot_updater_plugin_core_internal.insightsOverviewId)({
8
+ ...identity,
9
+ periodKind: identity.periodKind,
10
+ bucketStartMs: 0
11
+ });
12
+ /** The head columns besides its key: the whole event and its current release. */
13
+ const headFields = (event) => {
14
+ const { install_id: _, ...fields } = event;
15
+ return {
16
+ ...fields,
17
+ current_release_id: (0, _hot_updater_plugin_core_internal.currentInsightsReleaseId)(event)
18
+ };
19
+ };
20
+ /**
21
+ * The `insights_latest_by_bundle` field of a head's (from, to) pair. A head
22
+ * matches a `from` and a `to` predicate of one type at once only through its
23
+ * pair, so this gauge is what a count subtracts to count it once.
24
+ */
25
+ const PAIR_FIELD = "from_to";
26
+ /** The pair gauge's `bundle_id`: a hash of the two bundle ids, which fit no single 36-character column. */
27
+ const bundlePairKey = (from, to) => (0, _hot_updater_plugin_core_internal.insightsKey)(`${from.length}:${from}${to.length}:${to}`);
28
+ /** Moves a head's gauges: the distribution row, one row per bundle it references, and its pair. */
29
+ const countHead = (tx, head, delta) => {
30
+ const bucket = hourOf(head.received_at_ms);
31
+ const shardBy = head.install_id;
32
+ tx.aggregate("insights_distribution", {
33
+ channel: head.channel,
34
+ platform: head.platform,
35
+ app_version: head.app_version,
36
+ release_id: head.current_release_id ?? "",
37
+ bucket_start_ms: bucket
38
+ }, { latest_installations: delta }, { shardBy });
39
+ for (const field of ["from_bundle_id", "to_bundle_id"]) {
40
+ const bundleId = head[field];
41
+ if (bundleId === null) continue;
42
+ tx.aggregate("insights_latest_by_bundle", {
43
+ platform: head.platform,
44
+ channel: head.channel,
45
+ bundle_field: field,
46
+ bundle_id: bundleId,
47
+ type: head.type,
48
+ bucket_start_ms: bucket
49
+ }, { installations: delta }, { shardBy });
50
+ }
51
+ if (head.from_bundle_id !== null) tx.aggregate("insights_latest_by_bundle", {
52
+ platform: head.platform,
53
+ channel: head.channel,
54
+ bundle_field: PAIR_FIELD,
55
+ bundle_id: bundlePairKey(head.from_bundle_id, head.to_bundle_id),
56
+ type: head.type,
57
+ bucket_start_ms: bucket
58
+ }, { installations: delta }, { shardBy });
59
+ };
60
+ /**
61
+ * Counters and sketches for one event: release, channel, and usage rows, with
62
+ * day rollups for channel and usage; and its outcome rows, its bundle
63
+ * filter's hour and every event's day.
64
+ */
65
+ const countEvent = (tx, event) => {
66
+ const shardBy = event.install_id;
67
+ for (const delta of (0, _hot_updater_plugin_core_internal.insightsOverviewDeltas)(event)) {
68
+ const { bucketStartMs, ...parts } = delta.identity;
69
+ const periods = parts.scopeKind === "channel" || parts.scopeKind === "usage" ? [["hour", bucketStartMs], ["day", dayOf(event.received_at_ms)]] : [[parts.periodKind, bucketStartMs]];
70
+ for (const [periodKind, bucket] of periods) {
71
+ const key = {
72
+ identity: insightsIdentity({
73
+ ...parts,
74
+ periodKind
75
+ }),
76
+ bucket_start_ms: bucket
77
+ };
78
+ const counters = Object.fromEntries([
79
+ ["downloads", delta.downloads],
80
+ ["launches", delta.launches],
81
+ ["failed_launches", delta.failedLaunches]
82
+ ].filter(([, value]) => value !== 0));
83
+ if (Object.keys(counters).length > 0) tx.aggregate("insights_overview", key, counters, { shardBy });
84
+ const sketches = {
85
+ ...delta.launchIdentity === void 0 ? {} : { launch_users: (0, _hot_updater_plugin_core_internal.addInsightsDistinct)(null, delta.launchIdentity) },
86
+ ...delta.activityIdentity === void 0 ? {} : { activity_users: (0, _hot_updater_plugin_core_internal.addInsightsDistinct)(null, delta.activityIdentity) }
87
+ };
88
+ if (Object.keys(sketches).length > 0) tx.aggregate("insights_sketches", key, sketches, { shardBy });
89
+ }
90
+ }
91
+ tx.aggregate("insights_outcomes", {
92
+ platform: event.platform,
93
+ channel: event.channel,
94
+ type: event.type,
95
+ bundle_ref: event.type === "RECOVERED" ? `from:${event.from_bundle_id}` : `to:${event.to_bundle_id}`,
96
+ bucket_start_ms: hourOf(event.received_at_ms)
97
+ }, { events: 1 }, { shardBy });
98
+ tx.aggregate("insights_outcomes", {
99
+ ...require_schema.DAILY_EVENTS,
100
+ bucket_start_ms: dayOf(event.received_at_ms)
101
+ }, { events: 1 }, { shardBy });
102
+ };
103
+ const isNewer = (event, head) => event.received_at_ms !== head.received_at_ms ? event.received_at_ms > head.received_at_ms : (0, _hot_updater_plugin_core_internal.compareUtf8)(event.id, head.id) > 0;
104
+ /**
105
+ * Records one event in one transaction: one batch read of the event and its
106
+ * installation's head, one of the gauge and sketch rows it changes, then one
107
+ * write. A repeated id changes nothing, whichever installation sends it; an
108
+ * older event still counts in its own hour but never replaces the head.
109
+ */
110
+ const recordEvent = (db, event) => {
111
+ (0, _hot_updater_plugin_core_internal.assertBundleEventRow)(event);
112
+ return db.transaction(async (tx) => {
113
+ const [existing, previous] = await Promise.all([tx.findOne("bundle_events", { id: event.id }), tx.findOne("bundle_event_heads", { install_id: event.install_id })]);
114
+ if (existing !== null) return;
115
+ tx.create("bundle_events", event);
116
+ countEvent(tx, event);
117
+ const fields = headFields(event);
118
+ const head = {
119
+ ...fields,
120
+ install_id: event.install_id
121
+ };
122
+ if (previous !== null && !isNewer(head, previous)) return;
123
+ if (previous === null) tx.create("bundle_event_heads", head);
124
+ else {
125
+ countHead(tx, previous, -1);
126
+ tx.update("bundle_event_heads", previous, fields);
127
+ }
128
+ countHead(tx, head, 1);
129
+ });
130
+ };
131
+ //#endregion
132
+ exports.PAIR_FIELD = PAIR_FIELD;
133
+ exports.bundlePairKey = bundlePairKey;
134
+ exports.insightsIdentity = insightsIdentity;
135
+ exports.recordEvent = recordEvent;
@@ -0,0 +1,13 @@
1
+ import "../../database/database.cjs";
2
+ import "./schema.cjs";
3
+ import { BundleEventRow } from "@hot-updater/plugin-core";
4
+ import { InsightsOverviewIdentity } from "@hot-updater/plugin-core/internal";
5
+ //#region src/plugins/insights/recordEvent.d.ts
6
+ /** An overview or sketch row's scope and period; day periods roll up channel and usage rows. */
7
+ type InsightsIdentityParts = Omit<InsightsOverviewIdentity, "bucketStartMs" | "periodKind"> & {
8
+ readonly periodKind: InsightsOverviewIdentity["periodKind"] | "day";
9
+ };
10
+ /** The `identity` of an overview or sketch row: its scope and period, hashed. */
11
+ declare const insightsIdentity: (identity: InsightsIdentityParts) => string;
12
+ //#endregion
13
+ export { InsightsIdentityParts, insightsIdentity };
@@ -0,0 +1,13 @@
1
+ import "../../database/database.mjs";
2
+ import "./schema.mjs";
3
+ import { BundleEventRow } from "@hot-updater/plugin-core";
4
+ import { InsightsOverviewIdentity } from "@hot-updater/plugin-core/internal";
5
+ //#region src/plugins/insights/recordEvent.d.ts
6
+ /** An overview or sketch row's scope and period; day periods roll up channel and usage rows. */
7
+ type InsightsIdentityParts = Omit<InsightsOverviewIdentity, "bucketStartMs" | "periodKind"> & {
8
+ readonly periodKind: InsightsOverviewIdentity["periodKind"] | "day";
9
+ };
10
+ /** The `identity` of an overview or sketch row: its scope and period, hashed. */
11
+ declare const insightsIdentity: (identity: InsightsIdentityParts) => string;
12
+ //#endregion
13
+ export { InsightsIdentityParts, insightsIdentity };