@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,229 @@
1
+ import { defineAggregate, defineTable } from "../../database/schema";
2
+
3
+ export const HOUR_MS = 3_600_000;
4
+ export const DAY_MS = 86_400_000;
5
+
6
+ const MOVEMENTS = new Set(["UPDATE_DOWNLOADED", "UPDATE_APPLIED", "RECOVERED"]);
7
+
8
+ const bundleEvents = defineTable(
9
+ {
10
+ id: { type: "string", maxLength: 36 },
11
+ type: { type: "string", maxLength: 32 },
12
+ install_id: { type: "string", maxLength: 255 },
13
+ user_id: { type: "string", maxLength: 255, required: false },
14
+ from_release_id: { type: "string", maxLength: 36, required: false },
15
+ from_bundle_id: { type: "string", maxLength: 36, required: false },
16
+ to_release_id: { type: "string", maxLength: 36, required: false },
17
+ to_bundle_id: { type: "string", maxLength: 36 },
18
+ platform: { type: "string", maxLength: 16 },
19
+ app_version: { type: "string" },
20
+ channel: { type: "string" },
21
+ metadata: { type: "json" },
22
+ received_at_ms: { type: "integer" },
23
+ },
24
+ {
25
+ key: ["id"],
26
+ derived: {
27
+ /** The UTC day the event was received in. */
28
+ day: {
29
+ type: "integer",
30
+ compute: (row) => row.received_at_ms - (row.received_at_ms % DAY_MS),
31
+ },
32
+ /** Set only for events that belong in installation history. */
33
+ movement_install_id: {
34
+ type: "string",
35
+ compute: (row) => (MOVEMENTS.has(row.type) ? row.install_id : null),
36
+ },
37
+ /** The bundle a bundle filter matches: `from:<bundle>` for RECOVERED, else `to:<bundle>`. */
38
+ bundle_ref: {
39
+ type: "string",
40
+ multi: true,
41
+ compute: (row) => [
42
+ row.type === "RECOVERED" && row.from_bundle_id !== null
43
+ ? `from:${row.from_bundle_id}`
44
+ : `to:${row.to_bundle_id}`,
45
+ ],
46
+ },
47
+ },
48
+ indexes: {
49
+ recent: { eq: ["channel", "platform", "day"], sort: ["received_at_ms"] },
50
+ movementsByInstall: {
51
+ eq: ["movement_install_id"],
52
+ sort: ["received_at_ms"],
53
+ },
54
+ byBundle: {
55
+ eq: ["platform", "channel", "type", "bundle_ref", "day"],
56
+ sort: ["received_at_ms"],
57
+ },
58
+ /** Events of every scope by day, for the console's unfiltered event list. */
59
+ byDay: { eq: ["day"], sort: ["received_at_ms"] },
60
+ },
61
+ },
62
+ );
63
+
64
+ /** Each installation's latest event, whole, so reading it is one point read. */
65
+ const bundleEventHeads = defineTable(
66
+ {
67
+ install_id: { type: "string", maxLength: 255 },
68
+ id: { type: "string", maxLength: 36 },
69
+ type: { type: "string", maxLength: 32 },
70
+ user_id: { type: "string", maxLength: 255, required: false },
71
+ from_release_id: { type: "string", maxLength: 36, required: false },
72
+ from_bundle_id: { type: "string", maxLength: 36, required: false },
73
+ to_release_id: { type: "string", maxLength: 36, required: false },
74
+ to_bundle_id: { type: "string", maxLength: 36 },
75
+ platform: { type: "string", maxLength: 16 },
76
+ app_version: { type: "string" },
77
+ channel: { type: "string" },
78
+ metadata: { type: "json" },
79
+ received_at_ms: { type: "integer" },
80
+ current_release_id: { type: "string", maxLength: 36, required: false },
81
+ },
82
+ {
83
+ key: ["install_id"],
84
+ indexes: { byUser: { eq: ["user_id"], sort: ["install_id"] } },
85
+ },
86
+ );
87
+
88
+ /**
89
+ * Shards are keyed by install id. Counters are blind increments and never
90
+ * conflict, so they keep 8. Gauges and sketches are read, merged, and written
91
+ * back. B3's rollout gate on PostgreSQL retried 2.4% of transactions at 8
92
+ * shards and 1.3% at 16. DynamoDB's transactions take longer, so D8's gate
93
+ * on DynamoDB Local retried 2–24% at 16, almost all on gauge rows, and 1–5%
94
+ * with gauges at 32. Sketches stay at 16: each shard row carries 2 KB of
95
+ * registers that every read merges.
96
+ */
97
+ const COUNTER_SHARDS = 8;
98
+ const GAUGE_SHARDS = 32;
99
+ const SKETCH_SHARDS = 16;
100
+
101
+ /** Rows keyed by a hashed identity (scope and period) and a bucket. */
102
+ const identityFields = {
103
+ identity: { type: "string", maxLength: 32 },
104
+ bucket_start_ms: { type: "integer" },
105
+ } as const;
106
+ const window = { eq: ["identity"], sort: ["bucket_start_ms"] } as const;
107
+
108
+ const insightsOverview = defineAggregate(identityFields, {
109
+ key: ["identity", "bucket_start_ms"],
110
+ counters: ["downloads", "launches", "failed_launches"],
111
+ shards: COUNTER_SHARDS,
112
+ indexes: { window },
113
+ });
114
+
115
+ const insightsSketches = defineAggregate(identityFields, {
116
+ key: ["identity", "bucket_start_ms"],
117
+ distinct: ["launch_users", "activity_users"],
118
+ shards: SKETCH_SHARDS,
119
+ indexes: { window },
120
+ });
121
+
122
+ /** Installations counted in the hour of their latest event. */
123
+ const insightsDistribution = defineAggregate(
124
+ {
125
+ channel: { type: "string" },
126
+ platform: { type: "string", maxLength: 16 },
127
+ app_version: { type: "string" },
128
+ release_id: { type: "string", maxLength: 36 },
129
+ bucket_start_ms: { type: "integer" },
130
+ },
131
+ {
132
+ key: [
133
+ "channel",
134
+ "platform",
135
+ "app_version",
136
+ "release_id",
137
+ "bucket_start_ms",
138
+ ],
139
+ gauges: ["latest_installations"],
140
+ shards: GAUGE_SHARDS,
141
+ indexes: {
142
+ byScope: { eq: ["channel", "platform"], sort: ["bucket_start_ms"] },
143
+ byVersion: {
144
+ eq: ["channel", "platform", "app_version"],
145
+ sort: ["bucket_start_ms"],
146
+ },
147
+ },
148
+ },
149
+ );
150
+
151
+ /** Latest events by the bundle they came from or went to. */
152
+ const insightsLatestByBundle = defineAggregate(
153
+ {
154
+ platform: { type: "string", maxLength: 16 },
155
+ channel: { type: "string" },
156
+ bundle_field: { type: "string", maxLength: 16 },
157
+ bundle_id: { type: "string", maxLength: 36 },
158
+ type: { type: "string", maxLength: 32 },
159
+ bucket_start_ms: { type: "integer" },
160
+ },
161
+ {
162
+ key: [
163
+ "platform",
164
+ "channel",
165
+ "bundle_field",
166
+ "bundle_id",
167
+ "type",
168
+ "bucket_start_ms",
169
+ ],
170
+ gauges: ["installations"],
171
+ shards: GAUGE_SHARDS,
172
+ indexes: {
173
+ byBundle: {
174
+ eq: ["platform", "channel", "bundle_field", "bundle_id", "type"],
175
+ sort: ["bucket_start_ms"],
176
+ },
177
+ },
178
+ },
179
+ );
180
+
181
+ /**
182
+ * Events by outcome and the bundle a bundle filter matches, a row an hour;
183
+ * and every event, a row a UTC day (`DAILY_EVENTS`). Bundle counts sum the
184
+ * hourly rows, and event lists read either to skip days without events.
185
+ */
186
+ const insightsOutcomes = defineAggregate(
187
+ {
188
+ platform: { type: "string", maxLength: 16 },
189
+ channel: { type: "string" },
190
+ type: { type: "string", maxLength: 32 },
191
+ bundle_ref: { type: "string", maxLength: 41 },
192
+ bucket_start_ms: { type: "integer" },
193
+ },
194
+ {
195
+ key: ["platform", "channel", "type", "bundle_ref", "bucket_start_ms"],
196
+ counters: ["events"],
197
+ shards: COUNTER_SHARDS,
198
+ indexes: {
199
+ byRef: {
200
+ eq: ["platform", "channel", "type", "bundle_ref"],
201
+ sort: ["bucket_start_ms"],
202
+ },
203
+ },
204
+ },
205
+ );
206
+
207
+ /**
208
+ * The `insights_outcomes` identity that counts every event, for the global
209
+ * event list. Its bucket is a UTC day, not an hour. Every event's platform
210
+ * is ios or android, so no outcome row of a bundle filter shares it.
211
+ */
212
+ export const DAILY_EVENTS = {
213
+ platform: "*",
214
+ channel: "",
215
+ type: "",
216
+ bundle_ref: "",
217
+ } as const;
218
+
219
+ export const insightsSchema = {
220
+ bundle_events: bundleEvents,
221
+ bundle_event_heads: bundleEventHeads,
222
+ insights_overview: insightsOverview,
223
+ insights_sketches: insightsSketches,
224
+ insights_distribution: insightsDistribution,
225
+ insights_latest_by_bundle: insightsLatestByBundle,
226
+ insights_outcomes: insightsOutcomes,
227
+ } as const;
228
+
229
+ export type InsightsSchema = typeof insightsSchema;
@@ -0,0 +1,56 @@
1
+ import { createPluginTestHarness } from "@hot-updater/test-utils";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import * as engine from "../database";
5
+ import { defineTable } from "../database/schema";
6
+ import { definePlugin } from "./definePlugin";
7
+
8
+ const notes = definePlugin({
9
+ id: "notes",
10
+ schemaVersion: "1",
11
+ schema: {
12
+ notes: defineTable(
13
+ {
14
+ id: { type: "string" },
15
+ text: { type: "string" },
16
+ at: { type: "integer" },
17
+ },
18
+ { key: ["id"], indexes: { byTime: { eq: [], sort: ["at"] } } },
19
+ ),
20
+ },
21
+ init: ({ db, now }) => ({
22
+ api: {
23
+ add: (id: string, text: string) =>
24
+ db.transaction(async (tx) => {
25
+ tx.create("notes", { id, text, at: now() });
26
+ }),
27
+ latest: () =>
28
+ db.findMany("notes", {
29
+ index: "byTime",
30
+ where: {},
31
+ order: "desc",
32
+ limit: 2,
33
+ }),
34
+ },
35
+ }),
36
+ });
37
+
38
+ describe("plugin test harness", () => {
39
+ it("runs a plugin on a namespaced memory database and measures its reads", async () => {
40
+ const harness = await createPluginTestHarness(notes, {
41
+ engine,
42
+ now: () => 1,
43
+ });
44
+ await harness.api.add("a", "first");
45
+ harness.setNow(() => 2);
46
+ await harness.api.add("b", "second");
47
+ harness.setNow(() => 3);
48
+ await harness.api.add("c", "third");
49
+
50
+ expect(harness.tables.map(({ name }) => name)).toEqual(["notes_notes"]);
51
+ const measured = await harness.measureReads(() => harness.api.latest());
52
+ expect(measured.result.rows.map(({ id }) => id)).toEqual(["c", "b"]);
53
+ expect(measured.adapter.rows).toBe(measured.engine.rows);
54
+ expect(measured.engine).toEqual({ calls: 1, rows: 2 });
55
+ });
56
+ });
@@ -0,0 +1,15 @@
1
+ import type { ReadBudgetServer } from "@hot-updater/test-utils";
2
+
3
+ import { createMeasuredDatabase } from "./assembly/databasePlugins";
4
+ import { targetBaseCandidateKey } from "./core/baseCandidates";
5
+ import { builtInSchema } from "./db/builtInDatabase";
6
+ import { apiKeys } from "./plugins/api-keys";
7
+ import { insights } from "./plugins/insights";
8
+
9
+ /** The server parts `setupReadBudgetTestSuite` takes, for the server's own backends. */
10
+ export const readBudgetServer = {
11
+ createMeasuredDatabase,
12
+ builtInSchema,
13
+ plugins: [insights(), apiKeys()],
14
+ targetBaseCandidateKey,
15
+ } satisfies ReadBudgetServer;
@@ -1,96 +1,62 @@
1
1
  import { encodeChannelKey } from "@hot-updater/core";
2
- import { commitReleaseCatalogMutation } from "@hot-updater/plugin-core";
2
+ import type { EngineDatabase } from "@hot-updater/plugin-core";
3
3
  import { describe, expect, it, vi } from "vitest";
4
4
 
5
- import { createInMemoryDatabasePlugin } from "../../test-utils/test/inMemoryDatabasePlugin";
6
- import { registerApiKey } from "./apiKeys";
5
+ import { createDatabaseCoreApi } from "./core/api";
7
6
  import { createHotUpdater } from "./index";
7
+ import { apiKeys } from "./plugins/api-keys";
8
+ import { createRuntimeDatabase } from "./runtime.testFixtures";
8
9
 
9
10
  const API_KEY = "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE";
10
11
 
11
12
  const channelKey = encodeChannelKey("production");
12
13
  const scopeKey = `v1:app-version:ios:${channelKey}`;
13
14
 
15
+ /** A database with one deployed release in production's app-version scope. */
14
16
  const createCatalogDatabase = async () => {
15
- const database = createInMemoryDatabasePlugin();
16
- const channel = { id: "channel-production", name: "production" };
17
- await database.models.channels.insert({
18
- onConflict: "returnExisting",
19
- row: channel,
20
- });
21
- const bundleId = "00000000-0000-7001-8000-000000000001";
22
- await database.commit({
23
- changes: [
24
- {
25
- model: "bundles",
26
- operation: "insert",
27
- row: {
28
- asset_base_storage_uri: null,
29
- archive_byte_size: 3_000_000_001,
30
- file_hash: "bundle-hash",
31
- git_commit_hash: null,
32
- id: bundleId,
33
- manifest_file_hash: null,
34
- manifest_storage_uri: null,
35
- metadata: {},
36
- platform: "ios",
37
- storage_uri: "storage://bundle.zip",
38
- },
17
+ const database = createRuntimeDatabase();
18
+ await createDatabaseCoreApi(database).deploy([
19
+ {
20
+ bundle: {
21
+ assetBaseStorageUri: "storage://assets",
22
+ gitCommitHash: null,
23
+ id: "00000000-0000-7001-8000-000000000001",
24
+ manifestFileHash: "manifest-hash",
25
+ manifestStorageUri: "storage://bundle/manifest.json",
26
+ metadata: {},
27
+ platform: "ios",
39
28
  },
40
- ],
41
- });
42
- await commitReleaseCatalogMutation({
43
- database,
44
- mutation: {
45
- operation: "insert",
46
- row: {
47
- bundle_id: bundleId,
48
- channel_id: channel.id,
49
- created_at_ms: 1,
29
+ release: {
30
+ channel: "production",
50
31
  enabled: true,
51
- fingerprint_hash: null,
52
- id: "00000000-0000-7000-8000-000000000001",
53
- kind: "BUNDLE",
32
+ fingerprintHash: null,
54
33
  message: "Stable Release",
55
- operation: "DEPLOY",
56
- platform: "ios",
57
- revision: 1,
58
- rollout_cohort_count: 1000,
59
- scope_key: scopeKey,
60
- should_force_update: false,
61
- source_release_id: null,
62
- strategy: "APP_VERSION",
63
- target_app_version: ">=1.0.0 <2.0.0",
64
- target_cohorts: [],
65
- updated_at_ms: 1,
34
+ shouldForceUpdate: false,
35
+ targetAppVersion: ">=1.0.0 <2.0.0",
66
36
  },
67
37
  },
68
- scope: {
69
- channelId: channel.id,
70
- channelName: channel.name,
71
- fingerprintHash: null,
72
- platform: "ios",
73
- scopeKey,
74
- strategy: "APP_VERSION",
75
- },
76
- updatedAtMs: 1,
77
- });
38
+ ]);
78
39
  return database;
79
40
  };
80
41
 
42
+ /** Counts point reads of catalog rows, the update check's one read. */
43
+ const countCatalogReads = (database: EngineDatabase) => {
44
+ const get = vi.spyOn(database.adapter, "get");
45
+ return () =>
46
+ get.mock.calls.filter(([table]) => table.name === "release_catalogs")
47
+ .length;
48
+ };
49
+
81
50
  describe("Release catalog routes", () => {
82
51
  it("serves persisted Catalog identity without configuration and keeps it across server restarts", async () => {
83
52
  const database = await createCatalogDatabase();
84
53
  const storedCatalog =
85
- await database.models.releaseCatalogs.findByScopeKey(scopeKey);
54
+ await createDatabaseCoreApi(database).getReleaseCatalogRow(scopeKey);
55
+ const catalogReads = countCatalogReads(database);
86
56
  const hotUpdater = createHotUpdater({
87
57
  database,
88
- clientAccess: { type: "public" },
58
+ clientAccess: "public",
89
59
  });
90
- const catalogRead = vi.spyOn(
91
- database.models.releaseCatalogs,
92
- "findByScopeKey",
93
- );
94
60
  const url =
95
61
  `https://updates.example.com/release-catalogs/app-version/` +
96
62
  `ios/${channelKey}/1.5.0`;
@@ -132,7 +98,7 @@ describe("Release catalog routes", () => {
132
98
  );
133
99
  expect(revalidated.status).toBe(304);
134
100
  expect(await revalidated.text()).toBe("");
135
- expect(catalogRead).toHaveBeenCalledOnce();
101
+ expect(catalogReads()).toBe(1);
136
102
 
137
103
  const nonCanonicalVersion = await hotUpdater.handlers.client(
138
104
  new Request(url.replace("/1.5.0", "/v1.5")),
@@ -141,13 +107,13 @@ describe("Release catalog routes", () => {
141
107
  expect(nonCanonicalVersion.headers.get("cache-control")).toBe(
142
108
  "private, no-store",
143
109
  );
144
- expect(catalogRead).toHaveBeenCalledOnce();
110
+ expect(catalogReads()).toBe(1);
145
111
 
146
112
  const invalidPlatform = await hotUpdater.handlers.client(
147
113
  new Request(url.replace("/ios/", "/windows/")),
148
114
  );
149
115
  expect(invalidPlatform.status).toBe(400);
150
- expect(catalogRead).toHaveBeenCalledOnce();
116
+ expect(catalogReads()).toBe(1);
151
117
 
152
118
  const otherChannel = await hotUpdater.handlers.client(
153
119
  new Request(
@@ -155,7 +121,7 @@ describe("Release catalog routes", () => {
155
121
  ),
156
122
  );
157
123
  expect(otherChannel.status).toBe(404);
158
- expect(catalogRead).toHaveBeenCalledTimes(2);
124
+ expect(catalogReads()).toBe(2);
159
125
 
160
126
  const legacyAuthorityPath = await hotUpdater.handlers.client(
161
127
  new Request(
@@ -167,28 +133,25 @@ describe("Release catalog routes", () => {
167
133
  expect(legacyAuthorityPath.headers.get("cache-control")).toBe(
168
134
  "private, no-store",
169
135
  );
170
- expect(catalogRead).toHaveBeenCalledTimes(2);
171
- const commit = vi.spyOn(database, "commit");
136
+ expect(catalogReads()).toBe(2);
137
+ const write = vi.spyOn(database.adapter, "write");
172
138
  const restarted = createHotUpdater({
173
139
  database,
174
- clientAccess: { type: "public" },
140
+ clientAccess: "public",
175
141
  });
176
142
  const relocated = await restarted.handlers.client(
177
143
  new Request(url.replace("updates.example.com", "new.example.com")),
178
144
  );
179
145
  expect(await relocated.json()).toEqual(body);
180
- expect(commit).not.toHaveBeenCalled();
146
+ expect(write).not.toHaveBeenCalled();
181
147
  });
182
148
 
183
149
  it("singleflights concurrent cold requests into one exact catalog read", async () => {
184
150
  const database = await createCatalogDatabase();
185
- const catalogRead = vi.spyOn(
186
- database.models.releaseCatalogs,
187
- "findByScopeKey",
188
- );
151
+ const catalogReads = countCatalogReads(database);
189
152
  const hotUpdater = createHotUpdater({
190
153
  database,
191
- clientAccess: { type: "public" },
154
+ clientAccess: "public",
192
155
  });
193
156
  const url =
194
157
  `https://updates.example.com/release-catalogs/app-version/` +
@@ -201,23 +164,15 @@ describe("Release catalog routes", () => {
201
164
  );
202
165
 
203
166
  expect(responses.every(({ status }) => status === 200)).toBe(true);
204
- expect(catalogRead).toHaveBeenCalledOnce();
167
+ expect(catalogReads()).toBe(1);
205
168
  });
206
169
 
207
170
  it("varies authenticated catalog responses by the configured header", async () => {
208
- const database = await createCatalogDatabase();
209
- await registerApiKey({
210
- apiKeys: database.models.apiKeys,
211
- apiKey: API_KEY,
212
- name: "App",
213
- });
214
171
  const hotUpdater = createHotUpdater({
215
- clientAccess: {
216
- headerName: "X-Hot-Updater-Key",
217
- type: "api-key",
218
- },
219
- database,
172
+ database: await createCatalogDatabase(),
173
+ plugins: [apiKeys({ headerName: "X-Hot-Updater-Key" })],
220
174
  });
175
+ await hotUpdater.api.apiKeys.register({ apiKey: API_KEY, name: "App" });
221
176
  const url =
222
177
  `https://updates.example.com/release-catalogs/app-version/` +
223
178
  `ios/${channelKey}/1.5.0`;