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

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 (328) hide show
  1. package/LICENSE +12 -14
  2. package/dist/adapters/drizzle.cjs +32 -75
  3. package/dist/adapters/drizzle.d.cts +13 -5
  4. package/dist/adapters/drizzle.d.mts +13 -5
  5. package/dist/adapters/drizzle.mjs +32 -77
  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 +22 -31
  11. package/dist/adapters/kysely.d.cts +10 -6
  12. package/dist/adapters/kysely.d.mts +10 -6
  13. package/dist/adapters/kysely.mjs +23 -33
  14. package/dist/adapters/kyselyExecutor.cjs +32 -0
  15. package/dist/adapters/kyselyExecutor.d.cts +11 -0
  16. package/dist/adapters/kyselyExecutor.d.mts +11 -0
  17. package/dist/adapters/kyselyExecutor.mjs +32 -0
  18. package/dist/adapters/mongodb.cjs +18 -54
  19. package/dist/adapters/mongodb.d.cts +10 -5
  20. package/dist/adapters/mongodb.d.mts +10 -5
  21. package/dist/adapters/mongodb.mjs +19 -56
  22. package/dist/adapters/mongodbAdapter.cjs +192 -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 +191 -0
  26. package/dist/adapters/prisma.cjs +35 -267
  27. package/dist/adapters/prisma.d.cts +12 -7
  28. package/dist/adapters/prisma.d.mts +12 -7
  29. package/dist/adapters/prisma.mjs +36 -268
  30. package/dist/adapters/prismaExecutor.cjs +63 -0
  31. package/dist/adapters/prismaExecutor.mjs +63 -0
  32. package/dist/adapters/sqlProviders.cjs +14 -0
  33. package/dist/adapters/sqlProviders.mjs +14 -0
  34. package/dist/assembly/assemblePlugins.cjs +144 -0
  35. package/dist/assembly/assemblePlugins.d.cts +5 -0
  36. package/dist/assembly/assemblePlugins.d.mts +5 -0
  37. package/dist/assembly/assemblePlugins.mjs +139 -0
  38. package/dist/assembly/clientPlugins.cjs +88 -0
  39. package/dist/assembly/clientPlugins.mjs +88 -0
  40. package/dist/assembly/configError.d.cts +2 -0
  41. package/dist/assembly/configError.d.mts +2 -0
  42. package/dist/assembly/configError.mjs +2 -0
  43. package/dist/core/api.cjs +51 -0
  44. package/dist/core/api.d.cts +54 -0
  45. package/dist/core/api.d.mts +54 -0
  46. package/dist/core/api.mjs +51 -0
  47. package/dist/core/baseCandidates.cjs +28 -0
  48. package/dist/core/baseCandidates.mjs +28 -0
  49. package/dist/core/operations.cjs +351 -0
  50. package/dist/core/operations.mjs +351 -0
  51. package/dist/core/reads.cjs +273 -0
  52. package/dist/core/reads.d.cts +9 -0
  53. package/dist/core/reads.d.mts +9 -0
  54. package/dist/core/reads.mjs +267 -0
  55. package/dist/core/releases.cjs +193 -0
  56. package/dist/core/releases.mjs +190 -0
  57. package/dist/core/writes.cjs +96 -0
  58. package/dist/core/writes.mjs +91 -0
  59. package/dist/createHotUpdaterCore.cjs +72 -91
  60. package/dist/createHotUpdaterCore.d.cts +106 -38
  61. package/dist/createHotUpdaterCore.d.mts +106 -38
  62. package/dist/createHotUpdaterCore.mjs +74 -89
  63. package/dist/db/engineDrizzleSchema.cjs +53 -0
  64. package/dist/db/engineDrizzleSchema.mjs +53 -0
  65. package/dist/db/enginePrismaSchema.cjs +84 -0
  66. package/dist/db/enginePrismaSchema.d.cts +5 -0
  67. package/dist/db/enginePrismaSchema.d.mts +5 -0
  68. package/dist/db/enginePrismaSchema.mjs +83 -0
  69. package/dist/db/releaseCatalog.cjs +24 -47
  70. package/dist/db/releaseCatalog.mjs +20 -44
  71. package/dist/db/updateArtifacts.cjs +43 -72
  72. package/dist/db/updateArtifacts.mjs +40 -69
  73. package/dist/handler.cjs +59 -43
  74. package/dist/handler.d.cts +3 -5
  75. package/dist/handler.d.mts +3 -5
  76. package/dist/handler.mjs +61 -43
  77. package/dist/handlerAdminRoutes.cjs +374 -0
  78. package/dist/handlerAdminRoutes.mjs +372 -0
  79. package/dist/handlerParameters.cjs +6 -11
  80. package/dist/handlerParameters.mjs +6 -10
  81. package/dist/handlerReleaseCatalogRoutes.cjs +32 -15
  82. package/dist/handlerReleaseCatalogRoutes.mjs +32 -15
  83. package/dist/handlerTypes.d.cts +2 -55
  84. package/dist/handlerTypes.d.mts +2 -55
  85. package/dist/handlerVersionRoutes.cjs +20 -4
  86. package/dist/handlerVersionRoutes.mjs +20 -4
  87. package/dist/index.cjs +9 -9
  88. package/dist/index.d.cts +8 -9
  89. package/dist/index.d.mts +8 -9
  90. package/dist/index.mjs +3 -4
  91. package/dist/node.cjs +3 -6
  92. package/dist/node.d.cts +2 -2
  93. package/dist/node.d.mts +2 -2
  94. package/dist/node.mjs +4 -4
  95. package/dist/package.cjs +1 -1
  96. package/dist/package.mjs +1 -1
  97. package/dist/plugins/api-keys/index.cjs +9 -0
  98. package/dist/plugins/api-keys/index.d.cts +1 -0
  99. package/dist/plugins/api-keys/index.d.mts +1 -0
  100. package/dist/plugins/api-keys/index.mjs +2 -0
  101. package/dist/plugins/definePlugin.d.cts +2 -0
  102. package/dist/plugins/definePlugin.d.mts +2 -0
  103. package/dist/plugins/insights/index.cjs +9 -0
  104. package/dist/plugins/insights/index.d.cts +1 -0
  105. package/dist/plugins/insights/index.d.mts +1 -0
  106. package/dist/plugins/insights/index.mjs +2 -0
  107. package/dist/plugins/official.cjs +30 -0
  108. package/dist/plugins/official.mjs +29 -0
  109. package/dist/storageAccess.cjs +13 -10
  110. package/dist/storageAccess.mjs +13 -10
  111. package/dist/types/index.d.cts +2 -28
  112. package/dist/types/index.d.mts +2 -28
  113. package/package.json +26 -14
  114. package/dist/_virtual/_rolldown/runtime.cjs +0 -23
  115. package/dist/adapters/databaseConstraintErrors.cjs +0 -22
  116. package/dist/adapters/databaseConstraintErrors.mjs +0 -21
  117. package/dist/adapters/databasePluginUtils.cjs +0 -116
  118. package/dist/adapters/databasePluginUtils.mjs +0 -106
  119. package/dist/adapters/drizzleCrud.cjs +0 -311
  120. package/dist/adapters/drizzleCrud.mjs +0 -308
  121. package/dist/adapters/drizzleLazyDB.cjs +0 -106
  122. package/dist/adapters/drizzleLazyDB.mjs +0 -106
  123. package/dist/adapters/drizzleQuery.cjs +0 -69
  124. package/dist/adapters/drizzleQuery.mjs +0 -69
  125. package/dist/adapters/insightsTransaction.cjs +0 -22
  126. package/dist/adapters/insightsTransaction.mjs +0 -22
  127. package/dist/adapters/kyselyCrud.cjs +0 -305
  128. package/dist/adapters/kyselyCrud.mjs +0 -304
  129. package/dist/adapters/kyselyQuery.cjs +0 -56
  130. package/dist/adapters/kyselyQuery.mjs +0 -56
  131. package/dist/adapters/mongodbCollections.cjs +0 -38
  132. package/dist/adapters/mongodbCollections.mjs +0 -32
  133. package/dist/adapters/mongodbQuery.cjs +0 -94
  134. package/dist/adapters/mongodbQuery.mjs +0 -86
  135. package/dist/adapters/mongodbReads.cjs +0 -210
  136. package/dist/adapters/mongodbReads.mjs +0 -210
  137. package/dist/adapters/mongodbWrites.cjs +0 -148
  138. package/dist/adapters/mongodbWrites.mjs +0 -148
  139. package/dist/adapters/prismaQuery.cjs +0 -57
  140. package/dist/adapters/prismaQuery.mjs +0 -56
  141. package/dist/adapters/prismaRows.cjs +0 -219
  142. package/dist/adapters/prismaRows.mjs +0 -209
  143. package/dist/apiKeys.cjs +0 -143
  144. package/dist/apiKeys.d.cts +0 -49
  145. package/dist/apiKeys.d.mts +0 -49
  146. package/dist/apiKeys.mjs +0 -133
  147. package/dist/db/createBundleDiff.cjs +0 -144
  148. package/dist/db/createBundleDiff.d.cts +0 -16
  149. package/dist/db/createBundleDiff.d.mts +0 -16
  150. package/dist/db/createBundleDiff.mjs +0 -141
  151. package/dist/db/databasePluginCore.cjs +0 -137
  152. package/dist/db/databasePluginCore.mjs +0 -137
  153. package/dist/db/fixedMigrator.cjs +0 -79
  154. package/dist/db/fixedMigrator.mjs +0 -78
  155. package/dist/db/fixedMigratorMongo.cjs +0 -321
  156. package/dist/db/fixedMigratorMongo.mjs +0 -321
  157. package/dist/db/fixedMigratorShared.cjs +0 -23
  158. package/dist/db/fixedMigratorShared.mjs +0 -18
  159. package/dist/db/index.cjs +0 -27
  160. package/dist/db/index.d.cts +0 -12
  161. package/dist/db/index.d.mts +0 -12
  162. package/dist/db/index.mjs +0 -22
  163. package/dist/db/mongoMigrationExecution.cjs +0 -11
  164. package/dist/db/mongoMigrationExecution.mjs +0 -11
  165. package/dist/db/releaseCatalog.d.cts +0 -16
  166. package/dist/db/releaseCatalog.d.mts +0 -16
  167. package/dist/db/schema/insightsCollation.cjs +0 -14
  168. package/dist/db/schema/insightsCollation.mjs +0 -14
  169. package/dist/db/schema/mongodb.cjs +0 -25
  170. package/dist/db/schema/mongodb.mjs +0 -25
  171. package/dist/db/schema/registry.cjs +0 -21
  172. package/dist/db/schema/registry.mjs +0 -17
  173. package/dist/db/schema/sql.cjs +0 -105
  174. package/dist/db/schema/sql.mjs +0 -97
  175. package/dist/db/schema/sqlOperations.cjs +0 -27
  176. package/dist/db/schema/sqlOperations.mjs +0 -26
  177. package/dist/db/schemaGenerators.cjs +0 -275
  178. package/dist/db/schemaGenerators.mjs +0 -273
  179. package/dist/db/schemaReadiness.cjs +0 -26
  180. package/dist/db/schemaReadiness.d.cts +0 -9
  181. package/dist/db/schemaReadiness.d.mts +0 -9
  182. package/dist/db/schemaReadiness.mjs +0 -25
  183. package/dist/db/sqlMigrationExecution.cjs +0 -67
  184. package/dist/db/sqlMigrationExecution.mjs +0 -67
  185. package/dist/db/types.cjs +0 -22
  186. package/dist/db/types.d.cts +0 -118
  187. package/dist/db/types.d.mts +0 -118
  188. package/dist/db/types.mjs +0 -19
  189. package/dist/handlerBundleRoutes.cjs +0 -155
  190. package/dist/handlerBundleRoutes.mjs +0 -155
  191. package/dist/handlerReleaseManagementRoutes.cjs +0 -124
  192. package/dist/handlerReleaseManagementRoutes.mjs +0 -124
  193. package/dist/insights/domain.d.cts +0 -89
  194. package/dist/insights/domain.d.mts +0 -89
  195. package/dist/insights/errors.cjs +0 -15
  196. package/dist/insights/errors.mjs +0 -14
  197. package/dist/insights/eventInput.cjs +0 -155
  198. package/dist/insights/eventInput.mjs +0 -153
  199. package/dist/insights/provider.cjs +0 -314
  200. package/dist/insights/provider.d.cts +0 -6
  201. package/dist/insights/provider.d.mts +0 -6
  202. package/dist/insights/provider.mjs +0 -314
  203. package/dist/insights/queryInput.cjs +0 -93
  204. package/dist/insights/queryInput.mjs +0 -91
  205. package/dist/insights/routes.cjs +0 -58
  206. package/dist/insights/routes.mjs +0 -56
  207. package/dist/insights/types.d.cts +0 -32
  208. package/dist/insights/types.d.mts +0 -32
  209. package/dist/schema/dsl.cjs +0 -103
  210. package/dist/schema/dsl.mjs +0 -87
  211. package/dist/schema/index.cjs +0 -20
  212. package/dist/schema/index.mjs +0 -7
  213. package/dist/schema/settings.cjs +0 -9
  214. package/dist/schema/settings.mjs +0 -9
  215. package/dist/schema/types.cjs +0 -8
  216. package/dist/schema/types.mjs +0 -6
  217. package/dist/schema/v1_0_0.cjs +0 -406
  218. package/dist/schema/v1_0_0.mjs +0 -398
  219. package/src/adapters/databaseConstraintErrors.ts +0 -25
  220. package/src/adapters/databasePluginTestDatabase.ts +0 -120
  221. package/src/adapters/databasePluginUtils.spec.ts +0 -29
  222. package/src/adapters/databasePluginUtils.ts +0 -214
  223. package/src/adapters/drizzle.spec.ts +0 -336
  224. package/src/adapters/drizzle.ts +0 -162
  225. package/src/adapters/drizzleCrud.ts +0 -571
  226. package/src/adapters/drizzleLazyDB.ts +0 -271
  227. package/src/adapters/drizzleQuery.ts +0 -164
  228. package/src/adapters/insightsTransaction.ts +0 -32
  229. package/src/adapters/kysely.spec.ts +0 -174
  230. package/src/adapters/kysely.ts +0 -110
  231. package/src/adapters/kyselyCrud.ts +0 -709
  232. package/src/adapters/kyselyQuery.ts +0 -128
  233. package/src/adapters/mongodb.integration.spec.ts +0 -210
  234. package/src/adapters/mongodb.spec.ts +0 -209
  235. package/src/adapters/mongodb.ts +0 -138
  236. package/src/adapters/mongodbCollections.ts +0 -67
  237. package/src/adapters/mongodbQuery.ts +0 -255
  238. package/src/adapters/mongodbReads.ts +0 -380
  239. package/src/adapters/mongodbRows.spec.ts +0 -64
  240. package/src/adapters/mongodbRows.ts +0 -118
  241. package/src/adapters/mongodbTestClient.ts +0 -377
  242. package/src/adapters/mongodbTestFilter.ts +0 -169
  243. package/src/adapters/mongodbWrites.ts +0 -287
  244. package/src/adapters/prisma.spec.ts +0 -293
  245. package/src/adapters/prisma.ts +0 -565
  246. package/src/adapters/prismaQuery.ts +0 -129
  247. package/src/adapters/prismaRows.spec.ts +0 -98
  248. package/src/adapters/prismaRows.ts +0 -337
  249. package/src/adapters/prismaTestClient.ts +0 -413
  250. package/src/apiKeys.integration.spec.ts +0 -192
  251. package/src/apiKeys.spec.ts +0 -162
  252. package/src/apiKeys.ts +0 -220
  253. package/src/calculatePagination.ts +0 -34
  254. package/src/createHotUpdaterCore.ts +0 -246
  255. package/src/db/bundleRows.spec.ts +0 -164
  256. package/src/db/bundleRows.ts +0 -10
  257. package/src/db/createBundleDiff.spec.ts +0 -450
  258. package/src/db/createBundleDiff.ts +0 -364
  259. package/src/db/databasePluginCore.spec.ts +0 -62
  260. package/src/db/databasePluginCore.testFixtures.ts +0 -76
  261. package/src/db/databasePluginCore.ts +0 -185
  262. package/src/db/databasePluginUpdateCheck.bench.ts +0 -110
  263. package/src/db/fixedMigrator.spec.ts +0 -296
  264. package/src/db/fixedMigrator.ts +0 -147
  265. package/src/db/fixedMigratorMongo.spec.ts +0 -239
  266. package/src/db/fixedMigratorMongo.ts +0 -425
  267. package/src/db/fixedMigratorShared.ts +0 -36
  268. package/src/db/hotUpdaterSchema.ts +0 -5
  269. package/src/db/index.spec.ts +0 -1269
  270. package/src/db/index.ts +0 -47
  271. package/src/db/mongoMigrationExecution.ts +0 -23
  272. package/src/db/node-sqlite.d.ts +0 -25
  273. package/src/db/releaseCatalog.ts +0 -148
  274. package/src/db/schema/definitions.ts +0 -1
  275. package/src/db/schema/insightsCollation.ts +0 -21
  276. package/src/db/schema/mongodb.ts +0 -40
  277. package/src/db/schema/registry.ts +0 -55
  278. package/src/db/schema/sql.ts +0 -244
  279. package/src/db/schema/sqlOperations.ts +0 -63
  280. package/src/db/schema/types.ts +0 -1
  281. package/src/db/schemaGenerators.ts +0 -494
  282. package/src/db/schemaReadiness.ts +0 -34
  283. package/src/db/sqlMigrationExecution.spec.ts +0 -65
  284. package/src/db/sqlMigrationExecution.ts +0 -108
  285. package/src/db/types.spec.ts +0 -63
  286. package/src/db/types.ts +0 -228
  287. package/src/db/updateArtifacts.spec.ts +0 -359
  288. package/src/db/updateArtifacts.ts +0 -541
  289. package/src/handler-standalone.integration.spec.ts +0 -528
  290. package/src/handler.spec.ts +0 -190
  291. package/src/handler.testFixtures.ts +0 -30
  292. package/src/handler.ts +0 -245
  293. package/src/handlerAuth.integration.spec.ts +0 -33
  294. package/src/handlerBundleRoutes.ts +0 -259
  295. package/src/handlerErrors.ts +0 -7
  296. package/src/handlerManagement.spec.ts +0 -262
  297. package/src/handlerParameters.ts +0 -105
  298. package/src/handlerReleaseCatalogRoutes.ts +0 -154
  299. package/src/handlerReleaseManagementRoutes.ts +0 -213
  300. package/src/handlerTypes.ts +0 -96
  301. package/src/handlerVersionRoutes.ts +0 -12
  302. package/src/index.ts +0 -30
  303. package/src/insights/domain.ts +0 -103
  304. package/src/insights/errors.ts +0 -11
  305. package/src/insights/eventInput.ts +0 -225
  306. package/src/insights/insights.integration.spec.ts +0 -381
  307. package/src/insights/provider.spec.ts +0 -385
  308. package/src/insights/provider.ts +0 -591
  309. package/src/insights/queryInput.ts +0 -141
  310. package/src/insights/routes.ts +0 -104
  311. package/src/insights/types.ts +0 -55
  312. package/src/internalRouter.ts +0 -104
  313. package/src/node.spec.ts +0 -119
  314. package/src/node.ts +0 -111
  315. package/src/releaseCatalogRoutes.integration.spec.ts +0 -238
  316. package/src/runtime.spec.ts +0 -194
  317. package/src/runtime.testFixtures.ts +0 -71
  318. package/src/schema/dsl-all-versions.spec.ts +0 -37
  319. package/src/schema/dsl.ts +0 -187
  320. package/src/schema/index.ts +0 -10
  321. package/src/schema/settings.ts +0 -15
  322. package/src/schema/types.ts +0 -79
  323. package/src/schema/v1_0_0.spec.ts +0 -220
  324. package/src/schema/v1_0_0.ts +0 -529
  325. package/src/storageAccess.spec.ts +0 -152
  326. package/src/storageAccess.ts +0 -141
  327. package/src/types/index.ts +0 -34
  328. package/src/version.ts +0 -3
@@ -1,100 +1,85 @@
1
+ import { HotUpdaterConfigError } from "./assembly/configError.mjs";
2
+ import { clientPluginsOf } from "./assembly/clientPlugins.mjs";
3
+ import { assemblePlugins } from "./assembly/assemblePlugins.mjs";
1
4
  import { createHotUpdaterHandlers } from "./handler.mjs";
2
- import { createInsightsProvider } from "./insights/provider.mjs";
3
- import { authenticateApiKey, createApiKeyManagement, normalizeApiKeyHeaderName } from "./apiKeys.mjs";
4
- import { createDatabasePluginCore } from "./db/databasePluginCore.mjs";
5
- import { createSchemaReadinessChecker } from "./db/schemaReadiness.mjs";
6
- import { isDatabasePlugin } from "./db/types.mjs";
7
5
  import { createStorageAccess } from "./storageAccess.mjs";
8
6
  import { assertStorageOperations } from "@hot-updater/plugin-core";
9
7
  //#region src/createHotUpdaterCore.ts
10
- const normalizeClientAccess = (value) => {
11
- if (value === null || typeof value !== "object" || Array.isArray(value)) throw new TypeError("clientAccess must be an object.");
12
- const policy = value;
13
- if (policy.type === "public") return { type: "public" };
14
- if (policy.type === "api-key") return {
15
- headerName: normalizeApiKeyHeaderName(policy.headerName),
16
- type: "api-key"
17
- };
18
- throw new TypeError("clientAccess.type must be either \"public\" or \"api-key\".");
8
+ const isRecord = (value) => typeof value === "object" && value !== null;
9
+ const isAdapter = (value) => isRecord(value) && [
10
+ "fits",
11
+ "get",
12
+ "query",
13
+ "write"
14
+ ].every((method) => typeof value[method] === "function");
15
+ /** The configured database, when it runs on the storage engine. */
16
+ const databaseOf = (value) => {
17
+ if (isRecord(value) && typeof value.name === "string") {
18
+ if (isAdapter(value.adapter)) return value;
19
+ if ("core" in value && "fetchAdmin" in value) throw new HotUpdaterConfigError("standaloneRepository reaches a server's admin API from the CLI and console. createHotUpdater needs the server's own database, such as kyselyAdapter(...).");
20
+ }
21
+ throw new HotUpdaterConfigError("database must be a Hot Updater 1.0 database, such as kyselyAdapter(...) or postgres(...). Upgrade the provider package that created it.");
19
22
  };
20
- const hotUpdaterCoreMetadata = Symbol.for("@hot-updater/server/core-metadata");
21
- function getHotUpdaterCoreMetadata(hotUpdater) {
22
- return hotUpdater[hotUpdaterCoreMetadata];
23
- }
24
- function createHotUpdaterCore(options) {
23
+ /** `"public"`, or nothing; a `clientAccess` object says what replaced it. */
24
+ const isPublic = (value) => {
25
+ if (value === void 0) return false;
26
+ if (value === "public") return true;
27
+ throw new HotUpdaterConfigError(isRecord(value) ? "clientAccess objects were removed in 1.0. Set clientAccess: \"public\", or add a plugin that provides clientAuth to plugins." : "clientAccess must be \"public\"; to protect client routes, add a plugin that provides clientAuth to plugins.");
28
+ };
29
+ function createHotUpdater(options) {
25
30
  for (const key of ["authorityId", "catalogId"]) if (Object.hasOwn(options, key)) throw new TypeError(`Remove ${key} from createHotUpdater options. Catalog identity is managed internally.`);
26
- const database = options.database;
27
- const storagePlugins = (options.storage ?? []).map((storage) => {
28
- assertStorageOperations(storage, ["get", "getDownloadUrl"]);
29
- return storage;
30
- });
31
- const { downloadStorageObject, readStorageText, resolveFileUrl } = createStorageAccess(storagePlugins);
32
- const adapterCapabilities = database;
33
- if (!isDatabasePlugin(database)) throw new Error("@hot-updater/server only supports database plugins.");
34
- const plugin = database;
35
- const adapterName = adapterCapabilities.adapterName ?? plugin.name;
36
- const assertSchemaReady = createSchemaReadinessChecker(adapterName, adapterCapabilities.createMigrator);
37
- const core = createDatabasePluginCore(plugin, resolveFileUrl, {
38
- beforeOperation: assertSchemaReady,
39
- readStorageText
40
- });
41
- const clientAccess = normalizeClientAccess(options.clientAccess);
42
- const insights = createInsightsProvider({
43
- async record(input) {
44
- await assertSchemaReady();
45
- return plugin.models.insights.record(input);
46
- },
47
- async listEvents(input) {
48
- await assertSchemaReady();
49
- return plugin.models.insights.listEvents(input);
50
- },
51
- async findInstallations(input) {
52
- await assertSchemaReady();
53
- return plugin.models.insights.findInstallations(input);
54
- },
55
- async countInstallations(input) {
56
- await assertSchemaReady();
57
- return plugin.models.insights.countInstallations(input);
58
- },
59
- async countEvents(input) {
60
- await assertSchemaReady();
61
- return plugin.models.insights.countEvents(input);
62
- }
63
- });
64
- const apiKeys = createApiKeyManagement({
65
- apiKeys: plugin.models.apiKeys,
66
- beforeOperation: assertSchemaReady
67
- });
68
- const handlers = createHotUpdaterHandlers(core.api, insights, clientAccess.type === "api-key" ? {
69
- authenticate: (request) => authenticateApiKey({
70
- apiKeys: plugin.models.apiKeys,
71
- beforeLookup: assertSchemaReady,
72
- headerName: clientAccess.headerName,
73
- request
74
- }),
75
- headerName: clientAccess.headerName
76
- } : void 0, downloadStorageObject);
77
- const api = Object.assign({
78
- adapterName: adapterCapabilities.adapterName ?? core.adapterName,
79
- insights,
80
- apiKeys,
81
- handlers
82
- }, core.api);
83
- Object.defineProperty(api, hotUpdaterCoreMetadata, {
84
- enumerable: false,
85
- value: {
86
- adapterCapabilities,
87
- core
88
- }
31
+ const database = databaseOf(options.database);
32
+ const storage = Object.freeze([...options.storage ?? []]);
33
+ const { downloadStorageObject, readStorageText, resolveFileUrl } = createStorageAccess(storage);
34
+ const publicClients = isPublic(options.clientAccess);
35
+ const configured = Object.freeze([...options.plugins ?? []]);
36
+ const plugins = assemblePlugins(configured, database, { storage: {
37
+ readStorageText,
38
+ resolveFileUrl
39
+ } });
40
+ const clientPlugins = Object.freeze(clientPluginsOf(configured));
41
+ const clientAuth = plugins.clientAuth;
42
+ if (clientAuth !== void 0 && publicClients) throw new HotUpdaterConfigError(`Plugin "${clientAuth.plugin}" provides clientAuth, so remove clientAccess.`);
43
+ if (clientAuth === void 0 && !publicClients) throw new HotUpdaterConfigError("Set clientAccess to \"public\", or add a plugin that provides clientAuth.");
44
+ const varyHeaders = Object.freeze((clientAuth?.varyHeaders ?? []).map((header) => header.toLowerCase()));
45
+ const clientPolicy = clientAuth === void 0 ? void 0 : {
46
+ varyHeaders,
47
+ authenticate: (request) => clientAuth.authenticate(request.headers)
48
+ };
49
+ const handlers = createHotUpdaterHandlers({
50
+ api: { core: plugins.core },
51
+ ...clientPolicy === void 0 ? {} : { clientPolicy },
52
+ downloadStorageObject,
53
+ endpoints: plugins.endpoints,
54
+ plugins: Object.keys(plugins.api)
89
55
  });
56
+ let serving = false;
90
57
  return {
91
- api,
92
- adapterCapabilities,
93
- core
58
+ adapterName: database.name,
59
+ get handlers() {
60
+ if (!serving) {
61
+ for (const adapter of storage) assertStorageOperations(adapter, ["get", "getDownloadUrl"]);
62
+ serving = true;
63
+ }
64
+ return handlers;
65
+ },
66
+ core: plugins.core,
67
+ api: plugins.api,
68
+ flush: plugins.flush,
69
+ database,
70
+ storage,
71
+ plugins: configured,
72
+ clientPlugins,
73
+ clientEndpoints: Object.freeze(plugins.endpoints.filter((endpoint) => endpoint.access === "client").map(({ plugin, method, path }) => Object.freeze({
74
+ plugin,
75
+ method,
76
+ path
77
+ }))),
78
+ ...clientAuth === void 0 ? {} : { clientAuth: Object.freeze({
79
+ plugin: clientAuth.plugin,
80
+ varyHeaders
81
+ }) }
94
82
  };
95
83
  }
96
- function createHotUpdater(options) {
97
- return createHotUpdaterCore(options).api;
98
- }
99
84
  //#endregion
100
- export { createHotUpdater, createHotUpdaterCore, getHotUpdaterCoreMetadata, hotUpdaterCoreMetadata };
85
+ export { createHotUpdater };
@@ -0,0 +1,53 @@
1
+ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
2
+ //#region src/db/engineDrizzleSchema.ts
3
+ const drizzle = {
4
+ postgresql: {
5
+ module: "drizzle-orm/pg-core",
6
+ table: "pgTable"
7
+ },
8
+ mysql: {
9
+ module: "drizzle-orm/mysql-core",
10
+ table: "mysqlTable"
11
+ },
12
+ sqlite: {
13
+ module: "drizzle-orm/sqlite-core",
14
+ table: "sqliteTable"
15
+ }
16
+ };
17
+ const literal = (value) => JSON.stringify(value);
18
+ /**
19
+ * The Drizzle schema `drizzle-kit` applies for the engine's tables: every
20
+ * column typed exactly as the engine's DDL, keys, indexes, index tables, and
21
+ * the settings table. The engine keeps references itself, so there are no
22
+ * foreign keys. `hot-updater db migrate` then writes only the settings rows.
23
+ */
24
+ const generateDrizzleEngineSchema = (dialect, schema) => {
25
+ const { module, table: tableFunction } = drizzle[dialect];
26
+ const tables = [...schema.tables, _hot_updater_plugin_core.SETTINGS_TABLE];
27
+ const blocks = [];
28
+ const emit = (shape) => {
29
+ const columns = shape.columns.map((column) => ` ${literal(column.name)}: column(${literal(column.type)})(${literal(column.name)})${column.notNull ? ".notNull()" : ""}${column.default === void 0 ? "" : `.default(${column.default})`},`);
30
+ const at = (name) => `table[${literal(name)}]`;
31
+ const extras = [`primaryKey({ columns: [${shape.key.map(at).join(", ")}] })`, ...shape.indexes.flatMap((index) => index.kind === "index" ? [`${index.unique ? "uniqueIndex" : "index"}(${literal(index.name)}).on(${index.columns.map(at).join(", ")})`] : [])];
32
+ blocks.push(`export const ${shape.name} = ${tableFunction}(${literal(shape.name)}, {\n${columns.join("\n")}\n}, (table) => [\n${extras.map((extra) => ` ${extra},`).join("\n")}\n]);`);
33
+ for (const index of shape.indexes) if (index.kind === "table") emit(index.table);
34
+ };
35
+ for (const shape of (0, _hot_updater_plugin_core.sqlTableShapes)(dialect, tables)) emit(shape);
36
+ return [
37
+ "// Generated by `hot-updater db generate` from Hot Updater's schema. Do not edit.",
38
+ `import { ${[
39
+ "customType",
40
+ "index",
41
+ "primaryKey",
42
+ "uniqueIndex"
43
+ ].filter((name) => name === "customType" ? true : blocks.some((block) => block.includes(`${name}(`))).concat(tableFunction).sort().join(", ")} } from ${literal(module)};`,
44
+ "",
45
+ "/** A column typed exactly as Hot Updater's SQL schema declares it. */",
46
+ "const column = (type: string) =>",
47
+ " customType<{ data: unknown; driverData: unknown }>({ dataType: () => type });",
48
+ "",
49
+ ...blocks.flatMap((block) => [block, ""])
50
+ ].join("\n");
51
+ };
52
+ //#endregion
53
+ exports.generateDrizzleEngineSchema = generateDrizzleEngineSchema;
@@ -0,0 +1,53 @@
1
+ import { SETTINGS_TABLE, sqlTableShapes } from "@hot-updater/plugin-core";
2
+ //#region src/db/engineDrizzleSchema.ts
3
+ const drizzle = {
4
+ postgresql: {
5
+ module: "drizzle-orm/pg-core",
6
+ table: "pgTable"
7
+ },
8
+ mysql: {
9
+ module: "drizzle-orm/mysql-core",
10
+ table: "mysqlTable"
11
+ },
12
+ sqlite: {
13
+ module: "drizzle-orm/sqlite-core",
14
+ table: "sqliteTable"
15
+ }
16
+ };
17
+ const literal = (value) => JSON.stringify(value);
18
+ /**
19
+ * The Drizzle schema `drizzle-kit` applies for the engine's tables: every
20
+ * column typed exactly as the engine's DDL, keys, indexes, index tables, and
21
+ * the settings table. The engine keeps references itself, so there are no
22
+ * foreign keys. `hot-updater db migrate` then writes only the settings rows.
23
+ */
24
+ const generateDrizzleEngineSchema = (dialect, schema) => {
25
+ const { module, table: tableFunction } = drizzle[dialect];
26
+ const tables = [...schema.tables, SETTINGS_TABLE];
27
+ const blocks = [];
28
+ const emit = (shape) => {
29
+ const columns = shape.columns.map((column) => ` ${literal(column.name)}: column(${literal(column.type)})(${literal(column.name)})${column.notNull ? ".notNull()" : ""}${column.default === void 0 ? "" : `.default(${column.default})`},`);
30
+ const at = (name) => `table[${literal(name)}]`;
31
+ const extras = [`primaryKey({ columns: [${shape.key.map(at).join(", ")}] })`, ...shape.indexes.flatMap((index) => index.kind === "index" ? [`${index.unique ? "uniqueIndex" : "index"}(${literal(index.name)}).on(${index.columns.map(at).join(", ")})`] : [])];
32
+ blocks.push(`export const ${shape.name} = ${tableFunction}(${literal(shape.name)}, {\n${columns.join("\n")}\n}, (table) => [\n${extras.map((extra) => ` ${extra},`).join("\n")}\n]);`);
33
+ for (const index of shape.indexes) if (index.kind === "table") emit(index.table);
34
+ };
35
+ for (const shape of sqlTableShapes(dialect, tables)) emit(shape);
36
+ return [
37
+ "// Generated by `hot-updater db generate` from Hot Updater's schema. Do not edit.",
38
+ `import { ${[
39
+ "customType",
40
+ "index",
41
+ "primaryKey",
42
+ "uniqueIndex"
43
+ ].filter((name) => name === "customType" ? true : blocks.some((block) => block.includes(`${name}(`))).concat(tableFunction).sort().join(", ")} } from ${literal(module)};`,
44
+ "",
45
+ "/** A column typed exactly as Hot Updater's SQL schema declares it. */",
46
+ "const column = (type: string) =>",
47
+ " customType<{ data: unknown; driverData: unknown }>({ dataType: () => type });",
48
+ "",
49
+ ...blocks.flatMap((block) => [block, ""])
50
+ ].join("\n");
51
+ };
52
+ //#endregion
53
+ export { generateDrizzleEngineSchema };
@@ -0,0 +1,84 @@
1
+ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
2
+ //#region src/db/enginePrismaSchema.ts
3
+ const SCALARS = {
4
+ TEXT: "String",
5
+ INTEGER: "BigInt",
6
+ REAL: "Float",
7
+ bigint: "BigInt",
8
+ "double precision": "Float",
9
+ double: "Float",
10
+ boolean: "Boolean",
11
+ jsonb: "Json",
12
+ json: "Json"
13
+ };
14
+ /**
15
+ * A column's Prisma type from the DDL type the shared SQL schema gives it.
16
+ * MySQL's ASCII keys become `VarBinary`: the same bytes and order as
17
+ * `ascii_bin`, within InnoDB's key limit without a character set.
18
+ */
19
+ const prismaColumn = (provider, { type }) => {
20
+ const length = /^varchar\((\d+)\)/u.exec(type)?.[1];
21
+ if (provider === "mysql" && type.includes("CHARACTER SET")) {
22
+ if (type.includes("CHARACTER SET ascii") && length) return {
23
+ scalar: "Bytes",
24
+ native: `@db.VarBinary(${length})`
25
+ };
26
+ return {
27
+ scalar: "String",
28
+ native: length ? `@db.VarChar(${length})` : "@db.LongText",
29
+ collate: true
30
+ };
31
+ }
32
+ if (provider === "postgresql" && type.includes("COLLATE")) return {
33
+ scalar: "String",
34
+ ...length ? { native: `@db.VarChar(${length})` } : {},
35
+ collate: true
36
+ };
37
+ return { scalar: SCALARS[type] ?? "String" };
38
+ };
39
+ /** Prisma fields start with a letter: `_v` becomes `hu_v`, mapped back to `_v`. */
40
+ const fieldName = (column) => column.startsWith("_") ? `hu${column}` : column;
41
+ const list = (columns) => `[${columns.map(fieldName).join(", ")}]`;
42
+ const flatten = (shapes) => shapes.flatMap((shape) => [shape, ...flatten(shape.indexes.flatMap((index) => index.kind === "table" ? [index.table] : []))]);
43
+ const shapesOf = (provider, schema) => flatten((0, _hot_updater_plugin_core.sqlTableShapes)(provider, [...schema.tables, _hot_updater_plugin_core.SETTINGS_TABLE]));
44
+ const renderField = (provider, column) => {
45
+ const { scalar, native } = prismaColumn(provider, column);
46
+ const name = fieldName(column.name);
47
+ return [
48
+ `${name} ${scalar}${column.notNull ? "" : "?"}`,
49
+ ...native === void 0 ? [] : [native],
50
+ ...column.default === void 0 ? [] : [`@default(${column.default})`],
51
+ ...name === column.name ? [] : [`@map(${JSON.stringify(column.name)})`]
52
+ ].join(" ");
53
+ };
54
+ /**
55
+ * Hot Updater's tables as Prisma models, for `prisma db push` or
56
+ * `prisma migrate`: keys, indexes, index tables, and the settings table.
57
+ * The engine keeps references itself, so the models have no relations.
58
+ */
59
+ const generatePrismaEngineSchema = (provider, schema) => shapesOf(provider, schema).map((shape) => {
60
+ const lines = [
61
+ ...shape.columns.map((column) => renderField(provider, column)),
62
+ `@@id(${list(shape.key)})`,
63
+ ...shape.indexes.flatMap((index) => index.kind === "index" ? [`@@${index.unique ? "unique" : "index"}(${list(index.columns)}, map: ${JSON.stringify(index.name)})`] : [])
64
+ ];
65
+ return `model ${shape.name} {\n${lines.map((line) => ` ${line}`).join("\n")}\n}`;
66
+ }).join("\n\n");
67
+ /**
68
+ * The collations Prisma cannot declare, which `hot-updater db migrate` sets
69
+ * after Prisma created the tables: `COLLATE "C"` on PostgreSQL and binary
70
+ * UTF-8 on MySQL, so strings compare by their bytes as the engine expects.
71
+ * The settings table is only read by key, and the migrator has already read
72
+ * it: altering it would invalidate PostgreSQL's cached plan for that read.
73
+ */
74
+ const prismaCollationStatements = (provider, schema) => {
75
+ if (provider !== "postgresql" && provider !== "mysql") return [];
76
+ const quote = (name) => (0, _hot_updater_plugin_core.quoteSql)(provider, name);
77
+ return shapesOf(provider, schema).filter((shape) => shape.name !== _hot_updater_plugin_core.SETTINGS_TABLE.name).flatMap((shape) => {
78
+ const changes = shape.columns.filter((column) => prismaColumn(provider, column).collate).map((column) => provider === "postgresql" ? `ALTER COLUMN ${quote(column.name)} TYPE ${column.type}` : `MODIFY ${quote(column.name)} ${column.type}${column.notNull ? " NOT NULL" : " NULL"}`);
79
+ return changes.length === 0 ? [] : [`ALTER TABLE ${quote(shape.name)} ${changes.join(", ")}`];
80
+ });
81
+ };
82
+ //#endregion
83
+ exports.generatePrismaEngineSchema = generatePrismaEngineSchema;
84
+ exports.prismaCollationStatements = prismaCollationStatements;
@@ -0,0 +1,5 @@
1
+ import "@hot-updater/plugin-core";
2
+ //#region src/db/enginePrismaSchema.d.ts
3
+ type PrismaProvider = "postgresql" | "mysql" | "sqlite";
4
+ //#endregion
5
+ export { PrismaProvider };
@@ -0,0 +1,5 @@
1
+ import "@hot-updater/plugin-core";
2
+ //#region src/db/enginePrismaSchema.d.ts
3
+ type PrismaProvider = "postgresql" | "mysql" | "sqlite";
4
+ //#endregion
5
+ export { PrismaProvider };
@@ -0,0 +1,83 @@
1
+ import { SETTINGS_TABLE, quoteSql, sqlTableShapes } from "@hot-updater/plugin-core";
2
+ //#region src/db/enginePrismaSchema.ts
3
+ const SCALARS = {
4
+ TEXT: "String",
5
+ INTEGER: "BigInt",
6
+ REAL: "Float",
7
+ bigint: "BigInt",
8
+ "double precision": "Float",
9
+ double: "Float",
10
+ boolean: "Boolean",
11
+ jsonb: "Json",
12
+ json: "Json"
13
+ };
14
+ /**
15
+ * A column's Prisma type from the DDL type the shared SQL schema gives it.
16
+ * MySQL's ASCII keys become `VarBinary`: the same bytes and order as
17
+ * `ascii_bin`, within InnoDB's key limit without a character set.
18
+ */
19
+ const prismaColumn = (provider, { type }) => {
20
+ const length = /^varchar\((\d+)\)/u.exec(type)?.[1];
21
+ if (provider === "mysql" && type.includes("CHARACTER SET")) {
22
+ if (type.includes("CHARACTER SET ascii") && length) return {
23
+ scalar: "Bytes",
24
+ native: `@db.VarBinary(${length})`
25
+ };
26
+ return {
27
+ scalar: "String",
28
+ native: length ? `@db.VarChar(${length})` : "@db.LongText",
29
+ collate: true
30
+ };
31
+ }
32
+ if (provider === "postgresql" && type.includes("COLLATE")) return {
33
+ scalar: "String",
34
+ ...length ? { native: `@db.VarChar(${length})` } : {},
35
+ collate: true
36
+ };
37
+ return { scalar: SCALARS[type] ?? "String" };
38
+ };
39
+ /** Prisma fields start with a letter: `_v` becomes `hu_v`, mapped back to `_v`. */
40
+ const fieldName = (column) => column.startsWith("_") ? `hu${column}` : column;
41
+ const list = (columns) => `[${columns.map(fieldName).join(", ")}]`;
42
+ const flatten = (shapes) => shapes.flatMap((shape) => [shape, ...flatten(shape.indexes.flatMap((index) => index.kind === "table" ? [index.table] : []))]);
43
+ const shapesOf = (provider, schema) => flatten(sqlTableShapes(provider, [...schema.tables, SETTINGS_TABLE]));
44
+ const renderField = (provider, column) => {
45
+ const { scalar, native } = prismaColumn(provider, column);
46
+ const name = fieldName(column.name);
47
+ return [
48
+ `${name} ${scalar}${column.notNull ? "" : "?"}`,
49
+ ...native === void 0 ? [] : [native],
50
+ ...column.default === void 0 ? [] : [`@default(${column.default})`],
51
+ ...name === column.name ? [] : [`@map(${JSON.stringify(column.name)})`]
52
+ ].join(" ");
53
+ };
54
+ /**
55
+ * Hot Updater's tables as Prisma models, for `prisma db push` or
56
+ * `prisma migrate`: keys, indexes, index tables, and the settings table.
57
+ * The engine keeps references itself, so the models have no relations.
58
+ */
59
+ const generatePrismaEngineSchema = (provider, schema) => shapesOf(provider, schema).map((shape) => {
60
+ const lines = [
61
+ ...shape.columns.map((column) => renderField(provider, column)),
62
+ `@@id(${list(shape.key)})`,
63
+ ...shape.indexes.flatMap((index) => index.kind === "index" ? [`@@${index.unique ? "unique" : "index"}(${list(index.columns)}, map: ${JSON.stringify(index.name)})`] : [])
64
+ ];
65
+ return `model ${shape.name} {\n${lines.map((line) => ` ${line}`).join("\n")}\n}`;
66
+ }).join("\n\n");
67
+ /**
68
+ * The collations Prisma cannot declare, which `hot-updater db migrate` sets
69
+ * after Prisma created the tables: `COLLATE "C"` on PostgreSQL and binary
70
+ * UTF-8 on MySQL, so strings compare by their bytes as the engine expects.
71
+ * The settings table is only read by key, and the migrator has already read
72
+ * it: altering it would invalidate PostgreSQL's cached plan for that read.
73
+ */
74
+ const prismaCollationStatements = (provider, schema) => {
75
+ if (provider !== "postgresql" && provider !== "mysql") return [];
76
+ const quote = (name) => quoteSql(provider, name);
77
+ return shapesOf(provider, schema).filter((shape) => shape.name !== SETTINGS_TABLE.name).flatMap((shape) => {
78
+ const changes = shape.columns.filter((column) => prismaColumn(provider, column).collate).map((column) => provider === "postgresql" ? `ALTER COLUMN ${quote(column.name)} TYPE ${column.type}` : `MODIFY ${quote(column.name)} ${column.type}${column.notNull ? " NOT NULL" : " NULL"}`);
79
+ return changes.length === 0 ? [] : [`ALTER TABLE ${quote(shape.name)} ${changes.join(", ")}`];
80
+ });
81
+ };
82
+ //#endregion
83
+ export { generatePrismaEngineSchema, prismaCollationStatements };
@@ -1,65 +1,42 @@
1
- const require_updateArtifacts = require("./updateArtifacts.cjs");
2
1
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
3
- let _hot_updater_core = require("@hot-updater/core");
2
+ let _hot_updater_protocol = require("@hot-updater/protocol");
4
3
  //#region src/db/releaseCatalog.ts
4
+ /** A stored catalog payload, checked against its strategy's shape. */
5
5
  const parseCompiledCatalog = (payload, strategy) => {
6
6
  const parsed = JSON.parse(payload);
7
- if (typeof parsed !== "object" || parsed === null || Reflect.get(parsed, "schemaVersion") !== _hot_updater_core.RELEASE_CATALOG_SCHEMA_VERSION || Reflect.get(parsed, "strategy") !== strategy || Reflect.get(parsed, "fallbackPolicy") !== _hot_updater_core.RELEASE_CATALOG_FALLBACK_POLICY || !Array.isArray(Reflect.get(parsed, "releaseDescriptors"))) throw new Error("Stored Release catalog payload is invalid");
7
+ if (typeof parsed !== "object" || parsed === null || Reflect.get(parsed, "schemaVersion") !== _hot_updater_protocol.RELEASE_CATALOG_SCHEMA_VERSION || Reflect.get(parsed, "strategy") !== strategy || Reflect.get(parsed, "fallbackPolicy") !== _hot_updater_protocol.RELEASE_CATALOG_FALLBACK_POLICY || !Array.isArray(Reflect.get(parsed, "releaseDescriptors"))) throw new Error("Stored Release catalog payload is invalid");
8
8
  if (strategy === "APP_VERSION" && !Array.isArray(Reflect.get(parsed, "segments"))) throw new Error("Stored app-version Release catalog is invalid");
9
9
  if (strategy === "FINGERPRINT" && !Array.isArray(Reflect.get(parsed, "releaseIndexes"))) throw new Error("Stored fingerprint Release catalog is invalid");
10
10
  return parsed;
11
11
  };
12
- const createReleaseCatalogReader = (database) => async (input) => {
13
- const scopeKey = input.strategy === "APP_VERSION" ? (0, _hot_updater_core.createReleaseCatalogScopeKey)({
14
- channelKey: input.channelKey,
15
- platform: input.platform,
16
- strategy: "APP_VERSION"
17
- }) : (0, _hot_updater_core.createReleaseCatalogScopeKey)({
18
- channelKey: input.channelKey,
19
- fingerprintHash: input.fingerprintHash,
20
- platform: input.platform,
21
- strategy: "FINGERPRINT"
22
- });
23
- const row = await database.models.releaseCatalogs.findByScopeKey(scopeKey);
12
+ /** The scope key an update check reads. */
13
+ const releaseCatalogScopeKeyOf = (input) => input.strategy === "APP_VERSION" ? (0, _hot_updater_protocol.createReleaseCatalogScopeKey)({
14
+ channelKey: input.channelKey,
15
+ platform: input.platform,
16
+ strategy: "APP_VERSION"
17
+ }) : (0, _hot_updater_protocol.createReleaseCatalogScopeKey)({
18
+ channelKey: input.channelKey,
19
+ fingerprintHash: input.fingerprintHash,
20
+ platform: input.platform,
21
+ strategy: "FINGERPRINT"
22
+ });
23
+ /** Projects a stored catalog row for one update check; null when the row is not this scope's. */
24
+ const projectReleaseCatalogRow = (row, input, scopeKey = releaseCatalogScopeKeyOf(input)) => {
24
25
  if (row === null || row.platform !== input.platform || row.strategy !== input.strategy || row.channel_key !== input.channelKey || row.scope_key !== scopeKey || row.fingerprint_hash !== (input.strategy === "FINGERPRINT" ? input.fingerprintHash : null)) return null;
25
26
  const compiled = parseCompiledCatalog(row.payload, input.strategy);
26
- const releases = (0, _hot_updater_plugin_core.projectCompiledCatalog)(compiled, input.strategy === "APP_VERSION" ? input.appVersion : void 0);
27
- const rollbackReleases = (0, _hot_updater_plugin_core.projectCompiledRollbackCatalog)(compiled, input.strategy === "APP_VERSION" ? input.appVersion : void 0);
27
+ const appVersion = input.strategy === "APP_VERSION" ? input.appVersion : void 0;
28
28
  return {
29
29
  catalogId: row.catalog_id,
30
30
  catalogHash: row.catalog_hash,
31
- fallbackPolicy: _hot_updater_core.RELEASE_CATALOG_FALLBACK_POLICY,
31
+ fallbackPolicy: _hot_updater_protocol.RELEASE_CATALOG_FALLBACK_POLICY,
32
32
  generation: row.generation,
33
- releases,
34
- rollbackReleases,
35
- schemaVersion: _hot_updater_core.RELEASE_CATALOG_SCHEMA_VERSION,
33
+ releases: (0, _hot_updater_plugin_core.projectCompiledCatalog)(compiled, appVersion),
34
+ rollbackReleases: (0, _hot_updater_plugin_core.projectCompiledRollbackCatalog)(compiled, appVersion),
35
+ schemaVersion: _hot_updater_protocol.RELEASE_CATALOG_SCHEMA_VERSION,
36
36
  scopeKey
37
37
  };
38
38
  };
39
- const createArtifactResolver = (input) => {
40
- const databaseClient = (0, _hot_updater_plugin_core.createDatabaseClient)(input.database);
41
- return async (targetBundleId, currentBundleId) => {
42
- const [targetBundle, currentBundle] = await Promise.all([databaseClient.getBundleById(targetBundleId), currentBundleId === _hot_updater_core.NIL_UUID ? null : databaseClient.getBundleById(currentBundleId)]);
43
- if (targetBundle === null) return null;
44
- const fileUrl = await input.resolveFileUrl(targetBundle.storageUri);
45
- const base = {
46
- fileHash: targetBundle.fileHash,
47
- fileUrl
48
- };
49
- if (input.readStorageText === void 0) return base;
50
- const manifest = await require_updateArtifacts.resolveManifestArtifacts({
51
- archiveUrlUsable: fileUrl !== null,
52
- currentBundle,
53
- readStorageText: input.readStorageText,
54
- resolveFileUrl: input.resolveFileUrl,
55
- targetBundle
56
- });
57
- return manifest === null ? base : {
58
- ...base,
59
- ...manifest
60
- };
61
- };
62
- };
63
39
  //#endregion
64
- exports.createArtifactResolver = createArtifactResolver;
65
- exports.createReleaseCatalogReader = createReleaseCatalogReader;
40
+ exports.parseCompiledCatalog = parseCompiledCatalog;
41
+ exports.projectReleaseCatalogRow = projectReleaseCatalogRow;
42
+ exports.releaseCatalogScopeKeyOf = releaseCatalogScopeKeyOf;
@@ -1,7 +1,7 @@
1
- import { resolveManifestArtifacts } from "./updateArtifacts.mjs";
2
- import { createDatabaseClient, projectCompiledCatalog, projectCompiledRollbackCatalog } from "@hot-updater/plugin-core";
3
- import { NIL_UUID, RELEASE_CATALOG_FALLBACK_POLICY, RELEASE_CATALOG_SCHEMA_VERSION, createReleaseCatalogScopeKey } from "@hot-updater/core";
1
+ import { projectCompiledCatalog, projectCompiledRollbackCatalog } from "@hot-updater/plugin-core";
2
+ import { RELEASE_CATALOG_FALLBACK_POLICY, RELEASE_CATALOG_SCHEMA_VERSION, createReleaseCatalogScopeKey } from "@hot-updater/protocol";
4
3
  //#region src/db/releaseCatalog.ts
4
+ /** A stored catalog payload, checked against its strategy's shape. */
5
5
  const parseCompiledCatalog = (payload, strategy) => {
6
6
  const parsed = JSON.parse(payload);
7
7
  if (typeof parsed !== "object" || parsed === null || Reflect.get(parsed, "schemaVersion") !== RELEASE_CATALOG_SCHEMA_VERSION || Reflect.get(parsed, "strategy") !== strategy || Reflect.get(parsed, "fallbackPolicy") !== RELEASE_CATALOG_FALLBACK_POLICY || !Array.isArray(Reflect.get(parsed, "releaseDescriptors"))) throw new Error("Stored Release catalog payload is invalid");
@@ -9,56 +9,32 @@ const parseCompiledCatalog = (payload, strategy) => {
9
9
  if (strategy === "FINGERPRINT" && !Array.isArray(Reflect.get(parsed, "releaseIndexes"))) throw new Error("Stored fingerprint Release catalog is invalid");
10
10
  return parsed;
11
11
  };
12
- const createReleaseCatalogReader = (database) => async (input) => {
13
- const scopeKey = input.strategy === "APP_VERSION" ? createReleaseCatalogScopeKey({
14
- channelKey: input.channelKey,
15
- platform: input.platform,
16
- strategy: "APP_VERSION"
17
- }) : createReleaseCatalogScopeKey({
18
- channelKey: input.channelKey,
19
- fingerprintHash: input.fingerprintHash,
20
- platform: input.platform,
21
- strategy: "FINGERPRINT"
22
- });
23
- const row = await database.models.releaseCatalogs.findByScopeKey(scopeKey);
12
+ /** The scope key an update check reads. */
13
+ const releaseCatalogScopeKeyOf = (input) => input.strategy === "APP_VERSION" ? createReleaseCatalogScopeKey({
14
+ channelKey: input.channelKey,
15
+ platform: input.platform,
16
+ strategy: "APP_VERSION"
17
+ }) : createReleaseCatalogScopeKey({
18
+ channelKey: input.channelKey,
19
+ fingerprintHash: input.fingerprintHash,
20
+ platform: input.platform,
21
+ strategy: "FINGERPRINT"
22
+ });
23
+ /** Projects a stored catalog row for one update check; null when the row is not this scope's. */
24
+ const projectReleaseCatalogRow = (row, input, scopeKey = releaseCatalogScopeKeyOf(input)) => {
24
25
  if (row === null || row.platform !== input.platform || row.strategy !== input.strategy || row.channel_key !== input.channelKey || row.scope_key !== scopeKey || row.fingerprint_hash !== (input.strategy === "FINGERPRINT" ? input.fingerprintHash : null)) return null;
25
26
  const compiled = parseCompiledCatalog(row.payload, input.strategy);
26
- const releases = projectCompiledCatalog(compiled, input.strategy === "APP_VERSION" ? input.appVersion : void 0);
27
- const rollbackReleases = projectCompiledRollbackCatalog(compiled, input.strategy === "APP_VERSION" ? input.appVersion : void 0);
27
+ const appVersion = input.strategy === "APP_VERSION" ? input.appVersion : void 0;
28
28
  return {
29
29
  catalogId: row.catalog_id,
30
30
  catalogHash: row.catalog_hash,
31
31
  fallbackPolicy: RELEASE_CATALOG_FALLBACK_POLICY,
32
32
  generation: row.generation,
33
- releases,
34
- rollbackReleases,
33
+ releases: projectCompiledCatalog(compiled, appVersion),
34
+ rollbackReleases: projectCompiledRollbackCatalog(compiled, appVersion),
35
35
  schemaVersion: RELEASE_CATALOG_SCHEMA_VERSION,
36
36
  scopeKey
37
37
  };
38
38
  };
39
- const createArtifactResolver = (input) => {
40
- const databaseClient = createDatabaseClient(input.database);
41
- return async (targetBundleId, currentBundleId) => {
42
- const [targetBundle, currentBundle] = await Promise.all([databaseClient.getBundleById(targetBundleId), currentBundleId === NIL_UUID ? null : databaseClient.getBundleById(currentBundleId)]);
43
- if (targetBundle === null) return null;
44
- const fileUrl = await input.resolveFileUrl(targetBundle.storageUri);
45
- const base = {
46
- fileHash: targetBundle.fileHash,
47
- fileUrl
48
- };
49
- if (input.readStorageText === void 0) return base;
50
- const manifest = await resolveManifestArtifacts({
51
- archiveUrlUsable: fileUrl !== null,
52
- currentBundle,
53
- readStorageText: input.readStorageText,
54
- resolveFileUrl: input.resolveFileUrl,
55
- targetBundle
56
- });
57
- return manifest === null ? base : {
58
- ...base,
59
- ...manifest
60
- };
61
- };
62
- };
63
39
  //#endregion
64
- export { createArtifactResolver, createReleaseCatalogReader };
40
+ export { parseCompiledCatalog, projectReleaseCatalogRow, releaseCatalogScopeKeyOf };