@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
@@ -1,237 +1,306 @@
1
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { DatabaseSync, type SqliteValue } from "node:sqlite";
5
+ import { pathToFileURL } from "node:url";
6
+
1
7
  import { PGlite } from "@electric-sql/pglite";
2
8
  import {
3
- boolean,
4
- doublePrecision,
5
- integer,
6
- jsonb,
7
- pgTable,
8
- text,
9
- varchar,
10
- } from "drizzle-orm/pg-core";
11
- import { drizzle } from "drizzle-orm/pglite";
12
- import { describe, expect, it, vi } from "vitest";
13
-
14
- import { setupDatabasePluginTestSuite } from "../../../test-utils/src/setupDatabasePluginTestSuite";
15
- import type { DatabaseAdapterWithCapabilities } from "../db/types";
16
- import {
17
- DATABASE_PLUGIN_TEST_RESET_SQL,
18
- DATABASE_PLUGIN_TEST_SCHEMA_SQL,
19
- } from "./databasePluginTestDatabase";
20
- import { drizzleAdapter } from "./drizzle";
21
-
22
- const bundles = pgTable("bundles", {
23
- id: text("id").primaryKey(),
24
- platform: text("platform").notNull(),
25
- file_hash: text("file_hash").notNull(),
26
- git_commit_hash: text("git_commit_hash"),
27
- storage_uri: text("storage_uri").notNull(),
28
- archive_byte_size: doublePrecision("archive_byte_size").notNull(),
29
- metadata: jsonb("metadata").notNull(),
30
- manifest_storage_uri: text("manifest_storage_uri"),
31
- manifest_file_hash: text("manifest_file_hash"),
32
- asset_base_storage_uri: text("asset_base_storage_uri"),
33
- });
34
- const channels = pgTable("channels", {
35
- id: text("id").primaryKey(),
36
- name: text("name").notNull().unique(),
37
- });
38
- const releases = pgTable("releases", {
39
- id: text("id").primaryKey(),
40
- revision: integer("revision").notNull(),
41
- scope_key: text("scope_key").notNull(),
42
- channel_id: text("channel_id").notNull(),
43
- platform: text("platform").notNull(),
44
- kind: text("kind").notNull(),
45
- bundle_id: text("bundle_id"),
46
- strategy: text("strategy").notNull(),
47
- target_app_version: text("target_app_version"),
48
- fingerprint_hash: text("fingerprint_hash"),
49
- enabled: boolean("enabled").notNull(),
50
- should_force_update: boolean("should_force_update").notNull(),
51
- message: text("message"),
52
- rollout_cohort_count: integer("rollout_cohort_count").notNull(),
53
- target_cohorts: jsonb("target_cohorts").notNull(),
54
- operation: text("operation").notNull(),
55
- source_release_id: text("source_release_id"),
56
- created_at_ms: integer("created_at_ms").notNull(),
57
- updated_at_ms: integer("updated_at_ms").notNull(),
58
- });
59
- const releaseCatalogs = pgTable("release_catalogs", {
60
- scope_key: text("scope_key").primaryKey(),
61
- catalog_id: text("catalog_id").notNull(),
62
- strategy: text("strategy").notNull(),
63
- channel_id: text("channel_id").notNull(),
64
- channel_key: text("channel_key").notNull(),
65
- platform: text("platform").notNull(),
66
- fingerprint_hash: text("fingerprint_hash"),
67
- generation: integer("generation").notNull(),
68
- payload: text("payload").notNull(),
69
- catalog_hash: text("catalog_hash").notNull(),
70
- byte_size: integer("byte_size").notNull(),
71
- is_tombstone: boolean("is_tombstone").notNull(),
72
- updated_at_ms: integer("updated_at_ms").notNull(),
73
- });
74
- const bundlePatches = pgTable("bundle_patches", {
75
- id: varchar("id", { length: 255 }).primaryKey(),
76
- bundle_id: text("bundle_id").notNull(),
77
- base_bundle_id: text("base_bundle_id").notNull(),
78
- base_file_hash: text("base_file_hash").notNull(),
79
- patch_file_hash: text("patch_file_hash").notNull(),
80
- patch_storage_uri: text("patch_storage_uri").notNull(),
81
- byte_size: doublePrecision("byte_size").notNull(),
82
- order_index: integer("order_index").notNull(),
83
- });
84
- const bundleEvents = pgTable("bundle_events", {
85
- id: text("id").primaryKey(),
86
- type: text("type").notNull(),
87
- install_id: text("install_id").notNull(),
88
- user_id: text("user_id"),
89
- username: text("username"),
90
- from_release_id: text("from_release_id"),
91
- from_bundle_id: text("from_bundle_id"),
92
- to_release_id: text("to_release_id"),
93
- to_bundle_id: text("to_bundle_id").notNull(),
94
- platform: text("platform").notNull(),
95
- app_version: text("app_version").notNull(),
96
- channel: text("channel").notNull(),
97
- cohort: text("cohort").notNull(),
98
- update_strategy: text("update_strategy"),
99
- fingerprint_hash: text("fingerprint_hash"),
100
- sdk_version: text("sdk_version"),
101
- received_at_ms: integer("received_at_ms").notNull(),
102
- });
103
- const apiKeys = pgTable("api_keys", {
104
- id: text("id").primaryKey(),
105
- hash: text("hash").notNull().unique(),
106
- name: text("name").notNull(),
107
- prefix: text("prefix").notNull(),
108
- role: text("role").notNull(),
109
- created_at_ms: integer("created_at_ms").notNull(),
110
- revoked_at_ms: integer("revoked_at_ms"),
111
- });
112
- const schema = {
113
- bundle_events: bundleEvents,
114
- bundle_patches: bundlePatches,
115
- bundles,
116
- channels,
117
- api_keys: apiKeys,
118
- release_catalogs: releaseCatalogs,
119
- releases,
120
- };
9
+ setupDatabaseTestSuite,
10
+ startHttpTestServer,
11
+ } from "@hot-updater/test-utils";
12
+ import { createClient } from "@libsql/client";
13
+ import type { SQL } from "drizzle-orm";
14
+ import { drizzle as libsql } from "drizzle-orm/libsql";
15
+ import { drizzle as pglite } from "drizzle-orm/pglite";
16
+ import { SQLiteSyncDialect } from "drizzle-orm/sqlite-core";
17
+ import { afterAll, describe, expect, it } from "vitest";
121
18
 
122
- class DrizzleTestStateError extends Error {
123
- readonly name = "DrizzleTestStateError";
124
- }
19
+ import { createBundleFixture } from "../../../test-utils/src/databaseTestFixtures";
20
+ import { createDatabasePluginApis } from "../assembly/databasePlugins";
21
+ import { createInProcessCoreApi } from "../core/api";
22
+ import { HotUpdaterSchemaMigrationRequiredError } from "../database/fence";
23
+ import { createSqlAdapter } from "../database/sql/sqlAdapter";
24
+ import { isMultiIndex, quoteSql } from "../database/sql/sqlSchema";
25
+ import { builtInSchema, builtInSettings } from "../db/builtInDatabase";
26
+ import { generateEngineSql } from "../db/engineSql";
27
+ import type { ToolingDatabase } from "../db/types";
28
+ import { createHotUpdater } from "../index";
29
+ import { createInsightsModel, insights } from "../plugins/insights";
30
+ import {
31
+ drizzleAdapter,
32
+ DrizzleTransactionUnsupportedError,
33
+ type DrizzleProvider,
34
+ } from "./drizzle";
35
+ import { drizzleExecutor } from "./drizzleExecutor";
125
36
 
126
- let client: PGlite | undefined;
127
- let database: ReturnType<typeof drizzle<typeof schema>> | undefined;
37
+ /** Every data table; the settings rows stay across tests. */
38
+ const dataTables = builtInSchema.tables.flatMap((table) => [
39
+ table.name,
40
+ ...table.indexes
41
+ .filter((index) => isMultiIndex(table, index))
42
+ .map((index) => `${table.name}__${index.name}`),
43
+ ]);
128
44
 
129
- const getClient = (): PGlite => {
130
- if (client === undefined) throw new DrizzleTestStateError();
45
+ const temporaryDirectory = mkdtemp(
46
+ path.join(os.tmpdir(), "hot-updater-drizzle-"),
47
+ );
48
+ afterAll(async () =>
49
+ rm(await temporaryDirectory, { recursive: true, force: true }),
50
+ );
51
+ let files = 0;
52
+ const temporaryFile = async () =>
53
+ `file:${path.join(await temporaryDirectory, `${(files += 1)}.db`)}`;
54
+ /** A libSQL file in WAL mode, so reads never wait on a committing writer. */
55
+ const libsqlFile = async () => {
56
+ const client = createClient({ url: await temporaryFile() });
57
+ await client.execute("PRAGMA journal_mode = WAL");
131
58
  return client;
132
59
  };
133
60
 
134
- const getDatabase = (): ReturnType<typeof drizzle<typeof schema>> => {
135
- if (database === undefined) throw new DrizzleTestStateError();
136
- return database;
137
- };
61
+ const engineSql = (dialect: "postgresql" | "sqlite") =>
62
+ generateEngineSql(dialect, builtInSchema, builtInSettings);
138
63
 
139
- setupDatabasePluginTestSuite({
140
- name: "drizzleAdapter PostgreSQL",
141
- migrate: async () => {
142
- client = new PGlite();
143
- await client.exec(DATABASE_PLUGIN_TEST_SCHEMA_SQL);
144
- database = drizzle(client, { schema });
145
- },
146
- createPlugin: (): DatabaseAdapterWithCapabilities =>
147
- drizzleAdapter({ db: getDatabase(), provider: "postgresql" }),
148
- reset: async () => {
149
- await getClient().exec(DATABASE_PLUGIN_TEST_RESET_SQL);
64
+ const backends = {
65
+ postgresql: async () => {
66
+ const client = new PGlite();
67
+ await client.exec(engineSql("postgresql").join(";\n"));
68
+ return {
69
+ db: pglite(client),
70
+ exec: (sql: string) => client.exec(sql).then(() => undefined),
71
+ close: () => client.close(),
72
+ };
150
73
  },
151
- dispose: async () => {
152
- await getClient().close();
153
- database = undefined;
154
- client = undefined;
74
+ sqlite: async () => {
75
+ // A file: each libSQL transaction opens a connection, and `:memory:` would be a new database.
76
+ const client = await libsqlFile();
77
+ await client.executeMultiple(engineSql("sqlite").join(";\n"));
78
+ return {
79
+ db: libsql(client),
80
+ exec: (sql: string) => client.executeMultiple(sql),
81
+ close: async () => client.close(),
82
+ };
155
83
  },
156
- });
84
+ } as const;
157
85
 
158
- describe("drizzleAdapter schema requirements", () => {
159
- it("does not resolve a lazy database while generating a schema", () => {
160
- const getDB = vi.fn(() => {
161
- throw new DrizzleTestStateError();
162
- });
163
- const plugin = drizzleAdapter({
164
- db: getDB,
165
- provider: "postgresql",
166
- schema,
167
- });
168
-
169
- const generated = plugin.generateSchema?.("latest");
170
-
171
- expect(generated?.code).toContain("pgTable");
172
- expect(getDB).not.toHaveBeenCalled();
86
+ for (const provider of ["postgresql", "sqlite"] as const) {
87
+ let backend: Awaited<ReturnType<(typeof backends)[typeof provider]>>;
88
+ setupDatabaseTestSuite({
89
+ createHttpClient: (options) =>
90
+ startHttpTestServer(
91
+ createHotUpdater({
92
+ ...options,
93
+ plugins: [insights()],
94
+ clientAccess: "public",
95
+ }).handlers,
96
+ ),
97
+ createInsightsModel: (database) =>
98
+ createInsightsModel(
99
+ createDatabasePluginApis(database, [insights()]).insights,
100
+ ),
101
+ name: `drizzleAdapter (${provider})`,
102
+ migrate: async () => {
103
+ backend = await backends[provider]();
104
+ },
105
+ createDatabase: () => drizzleAdapter({ db: backend.db, provider }),
106
+ reset: async () => {
107
+ const quote = (name: string) => quoteSql(provider, name);
108
+ await backend.exec(
109
+ provider === "postgresql"
110
+ ? `TRUNCATE ${dataTables.map(quote).join(", ")} CASCADE`
111
+ : dataTables.map((name) => `DELETE FROM ${quote(name)};`).join(""),
112
+ );
113
+ },
114
+ dispose: () => backend.close(),
173
115
  });
116
+ }
174
117
 
175
- it("resolves a lazy database on the first database operation", async () => {
176
- const lazyClient = new PGlite();
177
- await lazyClient.exec(DATABASE_PLUGIN_TEST_SCHEMA_SQL);
178
- const lazyDatabase = drizzle(lazyClient, { schema });
179
- const getDB = vi.fn(async () => lazyDatabase);
180
- const plugin = drizzleAdapter({
181
- db: getDB,
182
- provider: "postgresql",
183
- schema,
184
- });
118
+ /** A sync Drizzle SQLite database as better-sqlite3's driver answers: over `node:sqlite`. */
119
+ const syncSqlite = (database: DatabaseSync) => {
120
+ const dialect = new SQLiteSyncDialect();
121
+ const prepare = (query: SQL) => {
122
+ const { sql, params } = dialect.sqlToQuery(query);
123
+ return {
124
+ statement: database.prepare(sql),
125
+ params: params as SqliteValue[],
126
+ };
127
+ };
128
+ return {
129
+ resultKind: "sync" as const,
130
+ all: (query: SQL) => {
131
+ const { statement, params } = prepare(query);
132
+ return statement.all(...params);
133
+ },
134
+ run: (query: SQL) => {
135
+ const { statement, params } = prepare(query);
136
+ return statement.run(...params);
137
+ },
138
+ };
139
+ };
185
140
 
186
- try {
187
- expect(getDB).not.toHaveBeenCalled();
188
- await expect(plugin.models.channels.list({})).resolves.toEqual({
189
- channels: [],
190
- });
191
- expect(getDB).toHaveBeenCalledOnce();
192
- } finally {
193
- await lazyClient.close();
194
- }
195
- });
141
+ const policy = {
142
+ channel: "production",
143
+ enabled: true,
144
+ fingerprintHash: null,
145
+ message: null,
146
+ shouldForceUpdate: false,
147
+ targetAppVersion: "1.0.0",
148
+ };
196
149
 
197
- it("rejects a lazy database without a schema on first use", () => {
198
- const getDB = vi.fn(() => {
199
- throw new DrizzleTestStateError();
200
- });
201
- const plugin = drizzleAdapter({ db: getDB, provider: "postgresql" });
150
+ /** Deploys bundle "1" through core on the database. */
151
+ const seed = async (database: ToolingDatabase) => {
152
+ const core = createInProcessCoreApi(database.adapter);
153
+ const bundle = createBundleFixture("1");
154
+ const [result] = await core.deploy([{ bundle, release: policy }]);
155
+ return { core, bundle, release: result!.release! };
156
+ };
202
157
 
203
- expect(() => plugin.models.channels.list({})).toThrow(
204
- "[hot-updater] Drizzle adapter requires schema when db is lazy.",
158
+ describe("drizzleAdapter drivers", () => {
159
+ it("runs a sync SQLite driver one statement at a time, with BEGIN IMMEDIATE transactions", async () => {
160
+ const database = new DatabaseSync(":memory:");
161
+ database.exec(engineSql("sqlite").join(";\n"));
162
+ const { core, bundle } = await seed(
163
+ drizzleAdapter({ db: syncSqlite(database), provider: "sqlite" }),
164
+ );
165
+ const deploys = Array.from({ length: 8 }, (_, n) =>
166
+ core.deploy([
167
+ { bundle: createBundleFixture(String(100 + n)), release: policy },
168
+ ]),
205
169
  );
206
- expect(getDB).not.toHaveBeenCalled();
170
+ await expect(Promise.all(deploys)).resolves.toHaveLength(8);
171
+ await expect(core.getBundle(bundle.id)).resolves.toMatchObject({
172
+ bundle: { id: bundle.id },
173
+ });
174
+ await expect(core.countBundles()).resolves.toBe(9);
175
+ database.close();
207
176
  });
208
177
 
209
- it("rejects an invalid lazy database schema on first use", () => {
210
- const getDB = vi.fn(() => {
211
- throw new DrizzleTestStateError();
212
- });
213
- const plugin = drizzleAdapter({
214
- db: getDB,
178
+ it("refuses a driver without interactive transactions on first use, naming the supported ones", async () => {
179
+ const client = new PGlite();
180
+ await client.exec(engineSql("postgresql").join(";\n"));
181
+ const db = pglite(client);
182
+ const withoutTransactions = {
183
+ execute: db.execute.bind(db),
184
+ transaction: () => {
185
+ throw new Error("No transactions support in neon-http driver");
186
+ },
187
+ };
188
+ const database = drizzleAdapter({
189
+ db: withoutTransactions,
215
190
  provider: "postgresql",
216
- schema: { ...schema, bundles: null },
217
191
  });
218
-
219
- expect(() => plugin.models.channels.list({})).toThrow(
220
- '[hot-updater] Drizzle schema table "bundles" is invalid.',
221
- );
222
- expect(getDB).not.toHaveBeenCalled();
192
+ const read = await createInProcessCoreApi(database.adapter)
193
+ .listChannels()
194
+ .catch((caught: unknown) => caught);
195
+ expect(read).toBeInstanceOf(DrizzleTransactionUnsupportedError);
196
+ expect(String(read)).toContain("better-sqlite3");
197
+ // Past the fence, a deploy reads in its transaction before it writes,
198
+ // so it stops there, before anything is sent.
199
+ const write = await createInProcessCoreApi(
200
+ createSqlAdapter({
201
+ executor: drizzleExecutor(withoutTransactions, "postgresql"),
202
+ }),
203
+ )
204
+ .deploy([{ bundle: createBundleFixture("2"), release: policy }])
205
+ .catch((caught: unknown) => caught);
206
+ expect(write).toBeInstanceOf(DrizzleTransactionUnsupportedError);
207
+ await client.close();
223
208
  });
224
209
 
225
- it("requires all fixed table objects on first use", () => {
226
- const incompleteSchema = { bundles };
227
- const plugin = drizzleAdapter({
228
- db: () => getDatabase(),
229
- provider: "postgresql",
230
- schema: incompleteSchema,
210
+ it("resolves a lazy database on first use", async () => {
211
+ let resolved = 0;
212
+ const database = drizzleAdapter({
213
+ db: async () => {
214
+ resolved += 1;
215
+ return (await backends.sqlite()).db;
216
+ },
217
+ provider: "sqlite",
231
218
  });
219
+ expect(resolved).toBe(0);
220
+ const { core } = await seed(database);
221
+ await core.listChannels();
222
+ expect(resolved).toBe(1);
223
+ });
224
+ });
225
+
226
+ describe("drizzleAdapter schema and migrations", () => {
227
+ const directory = mkdtemp(path.join(import.meta.dirname, ".drizzle-"));
228
+ afterAll(async () => rm(await directory, { recursive: true, force: true }));
229
+
230
+ /** The generated schema file, loaded as drizzle-kit loads it. */
231
+ const load = async (provider: DrizzleProvider) => {
232
+ const schema = drizzleAdapter({
233
+ db: {},
234
+ provider,
235
+ }).generateSchema!("latest");
236
+ const file = path.join(await directory, `${provider}.ts`);
237
+ await writeFile(file, schema.code);
238
+ expect(schema.path).toBe("hot-updater-schema.ts");
239
+ return (await import(pathToFileURL(file).href)) as Record<string, unknown>;
240
+ };
232
241
 
233
- expect(() => plugin.models.channels.list({})).toThrow(
234
- 'Drizzle schema is missing table "bundle_patches".',
242
+ it.each(["postgresql", "sqlite"] as const)(
243
+ "applies the generated %s schema with drizzle-kit, writes the settings with db migrate, and serves behind the fence",
244
+ async (provider) => {
245
+ const kit = await import("drizzle-kit/api");
246
+ const imports = await load(provider);
247
+ const statements =
248
+ provider === "postgresql"
249
+ ? await kit.generateMigration(
250
+ kit.generateDrizzleJson({}),
251
+ kit.generateDrizzleJson(imports),
252
+ )
253
+ : await kit.generateSQLiteMigration(
254
+ await kit.generateSQLiteDrizzleJson({}),
255
+ await kit.generateSQLiteDrizzleJson(imports),
256
+ );
257
+ const client =
258
+ provider === "postgresql" ? new PGlite() : await libsqlFile();
259
+ const run = async (sql: string) =>
260
+ client instanceof PGlite
261
+ ? client.exec(sql).then(() => undefined)
262
+ : client.executeMultiple(sql);
263
+ for (const statement of statements) await run(statement);
264
+ const db = client instanceof PGlite ? pglite(client) : libsql(client);
265
+ const database = drizzleAdapter({ db, provider });
266
+
267
+ await expect(
268
+ createInProcessCoreApi(database.adapter).listChannels(),
269
+ ).rejects.toBeInstanceOf(HotUpdaterSchemaMigrationRequiredError);
270
+ const migrator = database.createMigrator!();
271
+ const pending = await migrator.migrateToLatest();
272
+ expect(pending.operations).toEqual([
273
+ expect.objectContaining({ type: "custom" }),
274
+ ]);
275
+ await pending.execute();
276
+ await expect(migrator.migrateToLatest()).resolves.toMatchObject({
277
+ operations: [],
278
+ });
279
+ await expect(migrator.getVersion()).resolves.toBe("1.0.0");
280
+ const { core, release } = await seed(database);
281
+ await expect(core.getRelease(release.id)).resolves.toEqual(release);
282
+ await (client instanceof PGlite ? client.close() : client.close());
283
+ },
284
+ );
285
+
286
+ it("asks for the ORM's tables first, and refuses a database from before the engine", async () => {
287
+ const empty = await libsqlFile();
288
+ await expect(
289
+ drizzleAdapter({ db: libsql(empty), provider: "sqlite" })
290
+ .createMigrator!().migrateToLatest(),
291
+ ).rejects.toThrow("drizzle-kit push");
292
+
293
+ const legacy = await libsqlFile();
294
+ await legacy.executeMultiple(
295
+ "CREATE TABLE private_hot_updater_settings (key TEXT PRIMARY KEY, value TEXT NOT NULL); INSERT INTO private_hot_updater_settings VALUES ('schema.core', '1.0.0');",
235
296
  );
297
+ await expect(
298
+ drizzleAdapter({ db: libsql(legacy), provider: "sqlite" })
299
+ .createMigrator!().migrateToLatest(),
300
+ ).rejects.toMatchObject({
301
+ setting: { key: "schema.engine", expected: "1", found: null },
302
+ });
303
+ empty.close();
304
+ legacy.close();
236
305
  });
237
306
  });