@hot-updater/server 0.36.7 → 1.0.0-rc.0

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 (291) hide show
  1. package/dist/adapters/databaseConstraintErrors.cjs +23 -0
  2. package/dist/adapters/databaseConstraintErrors.mjs +21 -0
  3. package/dist/adapters/databasePluginUtils.cjs +117 -0
  4. package/dist/adapters/databasePluginUtils.mjs +106 -0
  5. package/dist/adapters/drizzle.cjs +53 -176
  6. package/dist/adapters/drizzle.d.cts +6 -4
  7. package/dist/adapters/drizzle.d.mts +6 -4
  8. package/dist/adapters/drizzle.mjs +54 -177
  9. package/dist/adapters/drizzleCrud.cjs +250 -0
  10. package/dist/adapters/drizzleCrud.mjs +249 -0
  11. package/dist/adapters/drizzleLazyDB.cjs +84 -36
  12. package/dist/adapters/drizzleLazyDB.mjs +84 -36
  13. package/dist/adapters/drizzleQuery.cjs +68 -0
  14. package/dist/adapters/drizzleQuery.mjs +67 -0
  15. package/dist/adapters/kysely.cjs +18 -138
  16. package/dist/adapters/kysely.d.cts +3 -12
  17. package/dist/adapters/kysely.d.mts +3 -12
  18. package/dist/adapters/kysely.mjs +19 -139
  19. package/dist/adapters/kyselyCrud.cjs +254 -0
  20. package/dist/adapters/kyselyCrud.mjs +253 -0
  21. package/dist/adapters/kyselyQuery.cjs +56 -0
  22. package/dist/adapters/kyselyQuery.mjs +55 -0
  23. package/dist/adapters/mongodb.cjs +21 -174
  24. package/dist/adapters/mongodb.d.cts +3 -2
  25. package/dist/adapters/mongodb.d.mts +3 -2
  26. package/dist/adapters/mongodb.mjs +21 -174
  27. package/dist/adapters/mongodbCollections.cjs +36 -0
  28. package/dist/adapters/mongodbCollections.mjs +30 -0
  29. package/dist/adapters/mongodbQuery.cjs +77 -0
  30. package/dist/adapters/mongodbQuery.mjs +70 -0
  31. package/dist/adapters/mongodbReads.cjs +148 -0
  32. package/dist/adapters/mongodbReads.mjs +147 -0
  33. package/dist/adapters/mongodbWrites.cjs +134 -0
  34. package/dist/adapters/mongodbWrites.mjs +133 -0
  35. package/dist/adapters/prisma.cjs +205 -180
  36. package/dist/adapters/prisma.d.cts +3 -3
  37. package/dist/adapters/prisma.d.mts +3 -3
  38. package/dist/adapters/prisma.mjs +206 -181
  39. package/dist/adapters/prismaQuery.cjs +58 -0
  40. package/dist/adapters/prismaQuery.mjs +56 -0
  41. package/dist/adapters/prismaRows.cjs +198 -0
  42. package/dist/adapters/prismaRows.mjs +188 -0
  43. package/dist/analytics/bounded/activeOverview.cjs +87 -0
  44. package/dist/analytics/bounded/activeOverview.mjs +85 -0
  45. package/dist/analytics/bounded/installationSearch.cjs +42 -0
  46. package/dist/analytics/bounded/installationSearch.mjs +42 -0
  47. package/dist/analytics/bounded/persistence.cjs +39 -0
  48. package/dist/analytics/bounded/persistence.mjs +38 -0
  49. package/dist/analytics/bounded/provider.cjs +170 -0
  50. package/dist/analytics/bounded/provider.d.cts +7 -0
  51. package/dist/analytics/bounded/provider.d.mts +7 -0
  52. package/dist/analytics/bounded/provider.mjs +170 -0
  53. package/dist/analytics/bounded/scan.cjs +144 -0
  54. package/dist/analytics/bounded/scan.mjs +138 -0
  55. package/dist/analytics/domain.d.cts +121 -0
  56. package/dist/analytics/domain.d.mts +121 -0
  57. package/dist/analytics/errors.cjs +22 -0
  58. package/dist/analytics/errors.mjs +20 -0
  59. package/dist/analytics/eventInput.cjs +111 -0
  60. package/dist/analytics/eventInput.mjs +111 -0
  61. package/dist/analytics/persistence.d.cts +6 -0
  62. package/dist/analytics/persistence.d.mts +6 -0
  63. package/dist/analytics/queryInput.cjs +58 -0
  64. package/dist/analytics/queryInput.mjs +55 -0
  65. package/dist/analytics/routes.cjs +63 -0
  66. package/dist/analytics/routes.mjs +61 -0
  67. package/dist/analytics/types.d.cts +17 -0
  68. package/dist/analytics/types.d.mts +17 -0
  69. package/dist/apiKeys.cjs +139 -0
  70. package/dist/apiKeys.d.cts +50 -0
  71. package/dist/apiKeys.d.mts +50 -0
  72. package/dist/apiKeys.mjs +133 -0
  73. package/dist/createHotUpdaterCore.cjs +48 -26
  74. package/dist/createHotUpdaterCore.d.cts +49 -17
  75. package/dist/createHotUpdaterCore.d.mts +49 -17
  76. package/dist/createHotUpdaterCore.mjs +51 -29
  77. package/dist/db/createBundleDiff.cjs +45 -68
  78. package/dist/db/createBundleDiff.d.cts +3 -3
  79. package/dist/db/createBundleDiff.d.mts +3 -3
  80. package/dist/db/createBundleDiff.mjs +47 -68
  81. package/dist/db/databasePluginCore.cjs +138 -0
  82. package/dist/db/databasePluginCore.mjs +137 -0
  83. package/dist/db/fixedMigrator.cjs +36 -93
  84. package/dist/db/fixedMigrator.mjs +36 -93
  85. package/dist/db/fixedMigratorMongo.cjs +319 -0
  86. package/dist/db/fixedMigratorMongo.mjs +319 -0
  87. package/dist/db/fixedMigratorShared.cjs +23 -0
  88. package/dist/db/fixedMigratorShared.mjs +18 -0
  89. package/dist/db/mongoMigrationExecution.cjs +11 -0
  90. package/dist/db/mongoMigrationExecution.mjs +11 -0
  91. package/dist/db/releaseCatalog.cjs +66 -0
  92. package/dist/db/releaseCatalog.d.cts +17 -0
  93. package/dist/db/releaseCatalog.d.mts +17 -0
  94. package/dist/db/releaseCatalog.mjs +64 -0
  95. package/dist/db/schema/mongodb.cjs +14 -6
  96. package/dist/db/schema/mongodb.mjs +14 -6
  97. package/dist/db/schema/registry.cjs +0 -2
  98. package/dist/db/schema/registry.mjs +1 -2
  99. package/dist/db/schema/sql.cjs +31 -14
  100. package/dist/db/schema/sql.mjs +32 -13
  101. package/dist/db/schema/sqlOperations.cjs +4 -4
  102. package/dist/db/schema/sqlOperations.mjs +5 -5
  103. package/dist/db/schemaGenerators.cjs +52 -18
  104. package/dist/db/schemaGenerators.mjs +52 -18
  105. package/dist/db/schemaReadiness.cjs +4 -3
  106. package/dist/db/schemaReadiness.mjs +4 -3
  107. package/dist/db/sqlMigrationExecution.cjs +67 -0
  108. package/dist/db/sqlMigrationExecution.mjs +66 -0
  109. package/dist/db/types.cjs +2 -6
  110. package/dist/db/types.d.cts +60 -16
  111. package/dist/db/types.d.mts +60 -16
  112. package/dist/db/types.mjs +3 -6
  113. package/dist/db/updateArtifacts.cjs +114 -60
  114. package/dist/db/updateArtifacts.mjs +117 -62
  115. package/dist/handler.cjs +108 -282
  116. package/dist/handler.d.cts +3 -46
  117. package/dist/handler.d.mts +3 -46
  118. package/dist/handler.mjs +107 -281
  119. package/dist/handlerBundleRoutes.cjs +155 -0
  120. package/dist/handlerBundleRoutes.mjs +155 -0
  121. package/dist/handlerErrors.cjs +9 -0
  122. package/dist/handlerErrors.mjs +9 -0
  123. package/dist/handlerParameters.cjs +39 -0
  124. package/dist/handlerParameters.mjs +34 -0
  125. package/dist/handlerReleaseCatalogRoutes.cjs +111 -0
  126. package/dist/handlerReleaseCatalogRoutes.mjs +110 -0
  127. package/dist/handlerReleaseManagementRoutes.cjs +125 -0
  128. package/dist/handlerReleaseManagementRoutes.mjs +124 -0
  129. package/dist/handlerTypes.d.cts +63 -0
  130. package/dist/handlerTypes.d.mts +63 -0
  131. package/dist/handlerVersionRoutes.cjs +10 -0
  132. package/dist/handlerVersionRoutes.d.cts +4 -0
  133. package/dist/handlerVersionRoutes.d.mts +4 -0
  134. package/dist/handlerVersionRoutes.mjs +9 -0
  135. package/dist/index.cjs +10 -1
  136. package/dist/index.d.cts +9 -3
  137. package/dist/index.d.mts +9 -3
  138. package/dist/index.mjs +5 -2
  139. package/dist/node.cjs +19 -12
  140. package/dist/node.d.cts +15 -10
  141. package/dist/node.d.mts +15 -10
  142. package/dist/node.mjs +19 -13
  143. package/dist/package.cjs +1 -1
  144. package/dist/package.mjs +1 -1
  145. package/dist/schema/dsl.cjs +19 -2
  146. package/dist/schema/dsl.mjs +17 -3
  147. package/dist/schema/index.cjs +1 -8
  148. package/dist/schema/index.mjs +2 -8
  149. package/dist/schema/types.cjs +3 -1
  150. package/dist/schema/types.mjs +3 -2
  151. package/dist/schema/v1_0_0.cjs +364 -0
  152. package/dist/schema/v1_0_0.mjs +357 -0
  153. package/dist/storageAccess.cjs +69 -25
  154. package/dist/storageAccess.mjs +68 -25
  155. package/dist/types/index.d.cts +4 -3
  156. package/dist/types/index.d.mts +5 -4
  157. package/package.json +8 -7
  158. package/src/adapters/databaseConstraintErrors.ts +25 -0
  159. package/src/adapters/databasePluginTestDatabase.ts +106 -0
  160. package/src/adapters/databasePluginUtils.spec.ts +29 -0
  161. package/src/adapters/databasePluginUtils.ts +214 -0
  162. package/src/adapters/drizzle.spec.ts +208 -47
  163. package/src/adapters/drizzle.ts +106 -293
  164. package/src/adapters/drizzleCrud.ts +419 -0
  165. package/src/adapters/drizzleLazyDB.ts +206 -100
  166. package/src/adapters/drizzleQuery.ts +164 -0
  167. package/src/adapters/kysely.spec.ts +126 -88
  168. package/src/adapters/kysely.ts +76 -334
  169. package/src/adapters/kyselyCrud.ts +588 -0
  170. package/src/adapters/kyselyQuery.ts +128 -0
  171. package/src/adapters/mongodb.spec.ts +141 -0
  172. package/src/adapters/mongodb.ts +60 -288
  173. package/src/adapters/mongodbCollections.ts +62 -0
  174. package/src/adapters/mongodbQuery.ts +226 -0
  175. package/src/adapters/mongodbReads.ts +311 -0
  176. package/src/adapters/mongodbRows.spec.ts +64 -0
  177. package/src/adapters/mongodbRows.ts +118 -0
  178. package/src/adapters/mongodbTestClient.ts +342 -0
  179. package/src/adapters/mongodbTestFilter.ts +166 -0
  180. package/src/adapters/mongodbWrites.ts +260 -0
  181. package/src/adapters/prisma.spec.ts +196 -0
  182. package/src/adapters/prisma.ts +417 -292
  183. package/src/adapters/prismaQuery.ts +129 -0
  184. package/src/adapters/prismaRows.spec.ts +98 -0
  185. package/src/adapters/prismaRows.ts +301 -0
  186. package/src/adapters/prismaTestClient.ts +396 -0
  187. package/src/analytics/analytics.integration.spec.ts +144 -0
  188. package/src/analytics/bounded/activeOverview.spec.ts +189 -0
  189. package/src/analytics/bounded/activeOverview.ts +148 -0
  190. package/src/analytics/bounded/installationSearch.spec.ts +130 -0
  191. package/src/analytics/bounded/installationSearch.ts +69 -0
  192. package/src/analytics/bounded/persistence.ts +43 -0
  193. package/src/analytics/bounded/provider.spec.ts +219 -0
  194. package/src/analytics/bounded/provider.ts +229 -0
  195. package/src/analytics/bounded/scan.ts +235 -0
  196. package/src/analytics/domain.ts +139 -0
  197. package/src/analytics/errors.ts +18 -0
  198. package/src/analytics/eventInput.ts +168 -0
  199. package/src/analytics/persistence.ts +10 -0
  200. package/src/analytics/queryInput.ts +102 -0
  201. package/src/analytics/routes.ts +123 -0
  202. package/src/analytics/types.ts +44 -0
  203. package/src/apiKeys.integration.spec.ts +192 -0
  204. package/src/apiKeys.spec.ts +162 -0
  205. package/src/apiKeys.ts +220 -0
  206. package/src/createHotUpdaterCore.ts +164 -100
  207. package/src/db/bundleRows.spec.ts +164 -0
  208. package/src/db/bundleRows.ts +10 -140
  209. package/src/db/createBundleDiff.spec.ts +172 -127
  210. package/src/db/createBundleDiff.ts +91 -110
  211. package/src/db/databasePluginCore.spec.ts +62 -0
  212. package/src/db/databasePluginCore.testFixtures.ts +76 -0
  213. package/src/db/databasePluginCore.ts +185 -0
  214. package/src/db/databasePluginUpdateCheck.bench.ts +107 -0
  215. package/src/db/fixedMigrator.spec.ts +184 -42
  216. package/src/db/fixedMigrator.ts +64 -205
  217. package/src/db/fixedMigratorMongo.spec.ts +192 -0
  218. package/src/db/fixedMigratorMongo.ts +425 -0
  219. package/src/db/fixedMigratorShared.ts +36 -0
  220. package/src/db/hotUpdaterSchema.ts +0 -1
  221. package/src/db/index.spec.ts +333 -1025
  222. package/src/db/mongoMigrationExecution.ts +23 -0
  223. package/src/db/node-sqlite.d.ts +25 -0
  224. package/src/db/releaseCatalog.ts +148 -0
  225. package/src/db/schema/mongodb.ts +20 -6
  226. package/src/db/schema/sql.ts +52 -11
  227. package/src/db/schema/sqlOperations.ts +5 -4
  228. package/src/db/schemaGenerators.ts +107 -23
  229. package/src/db/schemaReadiness.ts +2 -1
  230. package/src/db/sqlMigrationExecution.spec.ts +65 -0
  231. package/src/db/sqlMigrationExecution.ts +108 -0
  232. package/src/db/types.spec.ts +55 -0
  233. package/src/db/types.ts +129 -65
  234. package/src/db/updateArtifacts.spec.ts +359 -0
  235. package/src/db/updateArtifacts.ts +290 -126
  236. package/src/handler-standalone.integration.spec.ts +401 -364
  237. package/src/handler.spec.ts +137 -582
  238. package/src/handler.testFixtures.ts +30 -0
  239. package/src/handler.ts +218 -616
  240. package/src/handlerAuth.integration.spec.ts +33 -0
  241. package/src/handlerBundleRoutes.ts +259 -0
  242. package/src/handlerErrors.ts +7 -0
  243. package/src/handlerManagement.spec.ts +262 -0
  244. package/src/handlerParameters.ts +105 -0
  245. package/src/handlerReleaseCatalogRoutes.ts +154 -0
  246. package/src/handlerReleaseManagementRoutes.ts +213 -0
  247. package/src/handlerTypes.ts +96 -0
  248. package/src/handlerVersionRoutes.ts +12 -0
  249. package/src/index.ts +22 -2
  250. package/src/node.spec.ts +79 -10
  251. package/src/node.ts +20 -17
  252. package/src/releaseCatalogRoutes.integration.spec.ts +238 -0
  253. package/src/runtime.spec.ts +126 -959
  254. package/src/runtime.testFixtures.ts +71 -0
  255. package/src/schema/dsl-all-versions.spec.ts +26 -17
  256. package/src/schema/dsl.ts +41 -2
  257. package/src/schema/index.ts +3 -9
  258. package/src/schema/types.ts +9 -3
  259. package/src/schema/v1_0_0.spec.ts +146 -0
  260. package/src/schema/v1_0_0.ts +465 -0
  261. package/src/storageAccess.spec.ts +127 -32
  262. package/src/storageAccess.ts +106 -55
  263. package/src/types/index.ts +2 -1
  264. package/dist/db/bundleRows.cjs +0 -82
  265. package/dist/db/bundleRows.d.cts +0 -33
  266. package/dist/db/bundleRows.d.mts +0 -33
  267. package/dist/db/bundleRows.mjs +0 -79
  268. package/dist/db/pluginCore.cjs +0 -242
  269. package/dist/db/pluginCore.mjs +0 -241
  270. package/dist/db/schema/sqlMigrations.cjs +0 -74
  271. package/dist/db/schema/sqlMigrations.mjs +0 -73
  272. package/dist/db/schemaEnhancements.cjs +0 -20
  273. package/dist/db/schemaEnhancements.mjs +0 -19
  274. package/dist/route.cjs +0 -7
  275. package/dist/route.mjs +0 -7
  276. package/dist/schema/v0_21_0.cjs +0 -38
  277. package/dist/schema/v0_21_0.mjs +0 -37
  278. package/dist/schema/v0_29_0.cjs +0 -45
  279. package/dist/schema/v0_29_0.mjs +0 -44
  280. package/dist/schema/v0_31_0.cjs +0 -82
  281. package/dist/schema/v0_31_0.mjs +0 -80
  282. package/src/db/pluginCore.spec.ts +0 -1095
  283. package/src/db/pluginCore.ts +0 -475
  284. package/src/db/pluginUpdateCheck.bench.ts +0 -254
  285. package/src/db/schema/sqlMigrations.ts +0 -219
  286. package/src/db/schemaEnhancements.ts +0 -55
  287. package/src/route.ts +0 -7
  288. package/src/schema/v0_21_0.ts +0 -52
  289. package/src/schema/v0_29_0.ts +0 -62
  290. package/src/schema/v0_31_0.spec.ts +0 -73
  291. package/src/schema/v0_31_0.ts +0 -120
@@ -1,8 +1,9 @@
1
- import { HOT_UPDATER_SCHEMA_VERSION } from "../schema/types.mjs";
1
+ import "../schema/types.mjs";
2
+ import { unsupportedSchemaUpgradeMessage } from "./fixedMigratorShared.mjs";
2
3
  //#region src/db/schemaReadiness.ts
3
4
  var HotUpdaterSchemaMigrationRequiredError = class extends Error {
4
5
  constructor(adapterName, currentVersion) {
5
- super(currentVersion === void 0 ? `Hot Updater database schema is not initialized for ${adapterName}. Run \`hot-updater db migrate\` before using this adapter.` : `Hot Updater database schema version ${currentVersion} is not supported by ${adapterName}. Run \`hot-updater db migrate\` to upgrade to ${HOT_UPDATER_SCHEMA_VERSION}.`);
6
+ super(currentVersion === void 0 ? `Hot Updater database schema is not initialized for ${adapterName}. Run \`hot-updater db migrate\` before using this adapter.` : unsupportedSchemaUpgradeMessage(currentVersion));
6
7
  this.adapterName = adapterName;
7
8
  this.currentVersion = currentVersion;
8
9
  this.name = "HotUpdaterSchemaMigrationRequiredError";
@@ -14,7 +15,7 @@ const createSchemaReadinessChecker = (adapterName, createMigrator) => {
14
15
  return async () => {
15
16
  if (ready) return;
16
17
  const version = await createMigrator().getVersion();
17
- if (version !== "0.31.0") throw new HotUpdaterSchemaMigrationRequiredError(adapterName, version);
18
+ if (version !== "1.0.0") throw new HotUpdaterSchemaMigrationRequiredError(adapterName, version);
18
19
  ready = true;
19
20
  };
20
21
  };
@@ -0,0 +1,67 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ let kysely = require("kysely");
3
+ //#region src/db/sqlMigrationExecution.ts
4
+ var SqliteMigrationForeignKeyError = class extends Error {
5
+ name = "SqliteMigrationForeignKeyError";
6
+ constructor(violations) {
7
+ super(`SQLite migration produced ${violations} foreign key violation(s).`);
8
+ this.violations = violations;
9
+ }
10
+ };
11
+ const executeTransactionalStatements = async (db, statements) => {
12
+ await db.getExecutor().provideConnection(async (connection) => {
13
+ const execute = (statement) => connection.executeQuery(kysely.sql.raw(statement).compile(db));
14
+ await execute("begin");
15
+ try {
16
+ for (const statement of statements) await execute(statement);
17
+ await execute("commit");
18
+ } catch (error) {
19
+ await execute("rollback");
20
+ throw error;
21
+ }
22
+ });
23
+ };
24
+ const executeSqliteStatements = async (db, statements) => {
25
+ await db.getExecutor().provideConnection(async (connection) => {
26
+ const execute = (statement) => connection.executeQuery(kysely.sql.raw(statement).compile(db));
27
+ const state = (await execute("pragma foreign_keys")).rows[0];
28
+ const foreignKeysWereEnabled = typeof state === "object" && state !== null && "foreign_keys" in state && state.foreign_keys === 1;
29
+ await execute("pragma foreign_keys = off");
30
+ try {
31
+ await execute("begin");
32
+ try {
33
+ for (const statement of statements) {
34
+ if (statement === "pragma foreign_keys = off" || statement === "pragma foreign_keys = on") continue;
35
+ if (statement === "pragma foreign_key_check") {
36
+ const result = await execute(statement);
37
+ if (result.rows.length > 0) throw new SqliteMigrationForeignKeyError(result.rows.length);
38
+ continue;
39
+ }
40
+ await execute(statement);
41
+ }
42
+ await execute("commit");
43
+ } catch (error) {
44
+ await execute("rollback");
45
+ throw error;
46
+ }
47
+ } finally {
48
+ await execute(foreignKeysWereEnabled ? "pragma foreign_keys = on" : "pragma foreign_keys = off");
49
+ }
50
+ });
51
+ };
52
+ const executeMysqlStatements = async (db, statements) => {
53
+ for (const statement of statements) await kysely.sql.raw(statement).execute(db);
54
+ };
55
+ const executeMigrationStatements = async ({ db, provider, statements }) => {
56
+ if (provider === "mysql") {
57
+ await executeMysqlStatements(db, statements);
58
+ return;
59
+ }
60
+ if (provider === "sqlite") {
61
+ await executeSqliteStatements(db, statements);
62
+ return;
63
+ }
64
+ await executeTransactionalStatements(db, statements);
65
+ };
66
+ //#endregion
67
+ exports.executeMigrationStatements = executeMigrationStatements;
@@ -0,0 +1,66 @@
1
+ import { sql } from "kysely";
2
+ //#region src/db/sqlMigrationExecution.ts
3
+ var SqliteMigrationForeignKeyError = class extends Error {
4
+ name = "SqliteMigrationForeignKeyError";
5
+ constructor(violations) {
6
+ super(`SQLite migration produced ${violations} foreign key violation(s).`);
7
+ this.violations = violations;
8
+ }
9
+ };
10
+ const executeTransactionalStatements = async (db, statements) => {
11
+ await db.getExecutor().provideConnection(async (connection) => {
12
+ const execute = (statement) => connection.executeQuery(sql.raw(statement).compile(db));
13
+ await execute("begin");
14
+ try {
15
+ for (const statement of statements) await execute(statement);
16
+ await execute("commit");
17
+ } catch (error) {
18
+ await execute("rollback");
19
+ throw error;
20
+ }
21
+ });
22
+ };
23
+ const executeSqliteStatements = async (db, statements) => {
24
+ await db.getExecutor().provideConnection(async (connection) => {
25
+ const execute = (statement) => connection.executeQuery(sql.raw(statement).compile(db));
26
+ const state = (await execute("pragma foreign_keys")).rows[0];
27
+ const foreignKeysWereEnabled = typeof state === "object" && state !== null && "foreign_keys" in state && state.foreign_keys === 1;
28
+ await execute("pragma foreign_keys = off");
29
+ try {
30
+ await execute("begin");
31
+ try {
32
+ for (const statement of statements) {
33
+ if (statement === "pragma foreign_keys = off" || statement === "pragma foreign_keys = on") continue;
34
+ if (statement === "pragma foreign_key_check") {
35
+ const result = await execute(statement);
36
+ if (result.rows.length > 0) throw new SqliteMigrationForeignKeyError(result.rows.length);
37
+ continue;
38
+ }
39
+ await execute(statement);
40
+ }
41
+ await execute("commit");
42
+ } catch (error) {
43
+ await execute("rollback");
44
+ throw error;
45
+ }
46
+ } finally {
47
+ await execute(foreignKeysWereEnabled ? "pragma foreign_keys = on" : "pragma foreign_keys = off");
48
+ }
49
+ });
50
+ };
51
+ const executeMysqlStatements = async (db, statements) => {
52
+ for (const statement of statements) await sql.raw(statement).execute(db);
53
+ };
54
+ const executeMigrationStatements = async ({ db, provider, statements }) => {
55
+ if (provider === "mysql") {
56
+ await executeMysqlStatements(db, statements);
57
+ return;
58
+ }
59
+ if (provider === "sqlite") {
60
+ await executeSqliteStatements(db, statements);
61
+ return;
62
+ }
63
+ await executeTransactionalStatements(db, statements);
64
+ };
65
+ //#endregion
66
+ export { executeMigrationStatements };
package/dist/db/types.cjs CHANGED
@@ -8,11 +8,8 @@ const sqlProviders = [
8
8
  ];
9
9
  const noSqlProviders = ["mongodb"];
10
10
  [...sqlProviders, ...noSqlProviders];
11
- function isDatabasePluginFactory(adapter) {
12
- return typeof adapter === "function";
13
- }
14
- function isDatabasePlugin(adapter) {
15
- return typeof adapter === "object" && adapter !== null && "getBundleById" in adapter && "getBundles" in adapter && "getChannels" in adapter;
11
+ function isDatabasePlugin(plugin) {
12
+ return typeof plugin === "object" && plugin !== null && "name" in plugin && typeof plugin.name === "string" && "models" in plugin && typeof plugin.models === "object" && plugin.models !== null && "bundles" in plugin.models && typeof plugin.models.bundles === "object" && plugin.models.bundles !== null && "findById" in plugin.models.bundles && typeof plugin.models.bundles.findById === "function" && "findMany" in plugin.models.bundles && typeof plugin.models.bundles.findMany === "function" && "count" in plugin.models.bundles && typeof plugin.models.bundles.count === "function" && "bundlePatches" in plugin.models && typeof plugin.models.bundlePatches === "object" && plugin.models.bundlePatches !== null && "findByBundleIds" in plugin.models.bundlePatches && typeof plugin.models.bundlePatches.findByBundleIds === "function" && "channels" in plugin.models && typeof plugin.models.channels === "object" && plugin.models.channels !== null && "insert" in plugin.models.channels && typeof plugin.models.channels.insert === "function" && "list" in plugin.models.channels && typeof plugin.models.channels.list === "function" && "delete" in plugin.models.channels && typeof plugin.models.channels.delete === "function" && "analytics" in plugin.models && typeof plugin.models.analytics === "object" && plugin.models.analytics !== null && "append" in plugin.models.analytics && typeof plugin.models.analytics.append === "function" && "scan" in plugin.models.analytics && typeof plugin.models.analytics.scan === "function" && "apiKeys" in plugin.models && typeof plugin.models.apiKeys === "object" && plugin.models.apiKeys !== null && "create" in plugin.models.apiKeys && typeof plugin.models.apiKeys.create === "function" && "findByHash" in plugin.models.apiKeys && typeof plugin.models.apiKeys.findByHash === "function" && "list" in plugin.models.apiKeys && typeof plugin.models.apiKeys.list === "function" && "revoke" in plugin.models.apiKeys && typeof plugin.models.apiKeys.revoke === "function" && "commit" in plugin && typeof plugin.commit === "function" && (!("dispose" in plugin) || plugin.dispose === void 0 || typeof plugin.dispose === "function");
16
13
  }
17
14
  function getSQLProvider(provider) {
18
15
  if (!provider) return;
@@ -21,4 +18,3 @@ function getSQLProvider(provider) {
21
18
  //#endregion
22
19
  exports.getSQLProvider = getSQLProvider;
23
20
  exports.isDatabasePlugin = isDatabasePlugin;
24
- exports.isDatabasePluginFactory = isDatabasePluginFactory;
@@ -1,9 +1,11 @@
1
+ import { ReleaseCatalogRequest } from "./releaseCatalog.cjs";
1
2
  import { PaginatedResult } from "../types/index.cjs";
2
- import { AppUpdateAvailableInfo, Bundle, GetBundlesArgs, UpdateInfo } from "@hot-updater/core";
3
- import { DatabaseBundleQueryOptions, DatabasePlugin, HotUpdaterContext, RuntimeStoragePlugin } from "@hot-updater/plugin-core";
3
+ import * as _$_hot_updater_core0 from "@hot-updater/core";
4
+ import { ArtifactInfo, Bundle } from "@hot-updater/core";
5
+ import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
6
+ import { ChannelDeleteInput, ChannelDeleteResult, ChannelInsertInput, ChannelInsertResult, ChannelRow, DatabaseCommit, DatabaseCommitResult, DatabasePlugin, ReleaseCatalogMutationPreflight, ReleaseCatalogMutationResult, ReleaseCatalogRebuildResult, ReleaseCatalogRow, ReleasePolicyPatch, ReleaseRow } from "@hot-updater/plugin-core";
4
7
 
5
8
  //#region src/db/types.d.ts
6
- type DatabasePluginFactory<TContext = unknown> = (() => DatabasePlugin<TContext>) & Partial<DatabaseAdapterCapabilities>;
7
9
  declare const sqlProviders: readonly ["sqlite", "cockroachdb", "mysql", "postgresql", "mssql"];
8
10
  declare const providers: readonly ["sqlite", "cockroachdb", "mysql", "postgresql", "mssql", "mongodb"];
9
11
  type ORMProvider = (typeof providers)[number];
@@ -23,6 +25,9 @@ type MigrationOperation = {
23
25
  type: string;
24
26
  }>;
25
27
  };
28
+ } | {
29
+ type: "custom";
30
+ description: string;
26
31
  } | {
27
32
  type: "custom";
28
33
  sql: string;
@@ -60,18 +65,57 @@ interface DatabaseAdapterCapabilities {
60
65
  createMigrator?: () => Migrator;
61
66
  generateSchema?: SchemaGenerator;
62
67
  }
63
- type DatabaseAdapterWithCapabilities<TContext = unknown> = DatabasePlugin<TContext> & DatabaseAdapterCapabilities;
64
- type DatabaseAdapter<TContext = unknown> = DatabaseAdapterWithCapabilities<TContext> | DatabasePlugin<TContext> | DatabasePluginFactory<TContext>;
65
- interface DatabaseAPI<TContext = unknown> {
66
- getBundleById(id: string, context?: HotUpdaterContext<TContext>): Promise<Bundle | null>;
67
- getUpdateInfo(args: GetBundlesArgs, context?: HotUpdaterContext<TContext>): Promise<UpdateInfo | null>;
68
- getAppUpdateInfo(args: GetBundlesArgs, context?: HotUpdaterContext<TContext>): Promise<AppUpdateAvailableInfo | null>;
69
- getChannels(context?: HotUpdaterContext<TContext>): Promise<string[]>;
70
- getBundles(options: DatabaseBundleQueryOptions, context?: HotUpdaterContext<TContext>): Promise<PaginatedResult>;
71
- insertBundle(bundle: Bundle, context?: HotUpdaterContext<TContext>): Promise<void>;
72
- updateBundleById(bundleId: string, newBundle: Partial<Bundle>, context?: HotUpdaterContext<TContext>): Promise<void>;
73
- deleteBundleById(bundleId: string, context?: HotUpdaterContext<TContext>): Promise<void>;
68
+ type DatabaseAdapterWithCapabilities = DatabasePlugin & DatabaseAdapterCapabilities;
69
+ type DatabasePlugin$1 = DatabaseAdapterWithCapabilities;
70
+ interface DatabaseAPI {
71
+ getBundleById(id: string): Promise<Bundle | null>;
72
+ getReleaseCatalog(input: ReleaseCatalogRequest): Promise<_$_hot_updater_core0.ReleaseCatalog | null>;
73
+ getArtifactInfo(targetBundleId: string, currentBundleId: string): Promise<ArtifactInfo | null>;
74
+ getReleaseById(id: string): Promise<ReleaseRow | null>;
75
+ getReleasesByScope(input: {
76
+ readonly scopeKey: string;
77
+ readonly afterReleaseId?: string;
78
+ readonly limit: number;
79
+ }): Promise<readonly ReleaseRow[]>;
80
+ getReleases(input: {
81
+ readonly afterReleaseId?: string;
82
+ readonly beforeReleaseId?: string;
83
+ readonly bundleId?: string;
84
+ readonly channelId?: string;
85
+ readonly enabled?: boolean;
86
+ readonly platform?: "ios" | "android";
87
+ readonly targetAppVersion?: string;
88
+ readonly limit: number;
89
+ }): Promise<readonly ReleaseRow[]>;
90
+ getReleaseCatalogByScopeKey(scopeKey: string): Promise<ReleaseCatalogRow | null>;
91
+ getReleaseCatalogs(input: {
92
+ readonly afterScopeKey?: string;
93
+ readonly limit: number;
94
+ }): Promise<readonly ReleaseCatalogRow[]>;
95
+ updateReleasePolicy(input: {
96
+ readonly expectedRevision?: number;
97
+ readonly patch: ReleasePolicyPatch;
98
+ readonly releaseId: string;
99
+ }): Promise<ReleaseCatalogMutationResult>;
100
+ preflightReleasePolicy(input: {
101
+ readonly expectedRevision?: number;
102
+ readonly patch: ReleasePolicyPatch;
103
+ readonly releaseId: string;
104
+ }): Promise<ReleaseCatalogMutationPreflight>;
105
+ deleteRelease(input: {
106
+ readonly expectedRevision?: number;
107
+ readonly releaseId: string;
108
+ }): Promise<ReleaseCatalogMutationResult>;
109
+ rebuildReleaseCatalog(scopeKey: string): Promise<ReleaseCatalogRebuildResult>;
110
+ commitDatabase(input: DatabaseCommit): Promise<DatabaseCommitResult>;
111
+ getChannels(): Promise<readonly ChannelRow[]>;
112
+ insertChannel(input: ChannelInsertInput): Promise<ChannelInsertResult>;
113
+ deleteChannel(input: ChannelDeleteInput): Promise<ChannelDeleteResult>;
114
+ getBundles(options: _$_hot_updater_plugin_core0.DatabaseBundleQueryOptions): Promise<PaginatedResult>;
115
+ insertBundle(bundle: Bundle): Promise<void>;
116
+ insertBundles(bundles: readonly Bundle[]): Promise<void>;
117
+ updateBundleById(bundleId: string, newBundle: Partial<Bundle>): Promise<void>;
118
+ deleteBundleById(bundleId: string): Promise<void>;
74
119
  }
75
- type StoragePluginFactory<TContext = unknown> = () => RuntimeStoragePlugin<TContext>;
76
120
  //#endregion
77
- export { DatabaseAPI, DatabaseAdapter, DatabasePluginFactory, Migrator, ORMProvider, ORMSQLProvider, RelationMode, SchemaGenerator, StoragePluginFactory };
121
+ export { DatabaseAPI, DatabaseAdapterWithCapabilities, DatabasePlugin$1 as DatabasePlugin, Migrator, ORMProvider, ORMSQLProvider, RelationMode, SchemaGenerator };
@@ -1,9 +1,11 @@
1
+ import { ReleaseCatalogRequest } from "./releaseCatalog.mjs";
1
2
  import { PaginatedResult } from "../types/index.mjs";
2
- import { DatabaseBundleQueryOptions, DatabasePlugin, HotUpdaterContext, RuntimeStoragePlugin } from "@hot-updater/plugin-core";
3
- import { AppUpdateAvailableInfo, Bundle as Bundle$1, GetBundlesArgs, UpdateInfo } from "@hot-updater/core";
3
+ import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
4
+ import { ChannelDeleteInput, ChannelDeleteResult, ChannelInsertInput, ChannelInsertResult, ChannelRow, DatabaseCommit, DatabaseCommitResult, DatabasePlugin, ReleaseCatalogMutationPreflight, ReleaseCatalogMutationResult, ReleaseCatalogRebuildResult, ReleaseCatalogRow, ReleasePolicyPatch, ReleaseRow } from "@hot-updater/plugin-core";
5
+ import * as _$_hot_updater_core0 from "@hot-updater/core";
6
+ import { ArtifactInfo, Bundle as Bundle$1 } from "@hot-updater/core";
4
7
 
5
8
  //#region src/db/types.d.ts
6
- type DatabasePluginFactory<TContext = unknown> = (() => DatabasePlugin<TContext>) & Partial<DatabaseAdapterCapabilities>;
7
9
  declare const sqlProviders: readonly ["sqlite", "cockroachdb", "mysql", "postgresql", "mssql"];
8
10
  declare const providers: readonly ["sqlite", "cockroachdb", "mysql", "postgresql", "mssql", "mongodb"];
9
11
  type ORMProvider = (typeof providers)[number];
@@ -23,6 +25,9 @@ type MigrationOperation = {
23
25
  type: string;
24
26
  }>;
25
27
  };
28
+ } | {
29
+ type: "custom";
30
+ description: string;
26
31
  } | {
27
32
  type: "custom";
28
33
  sql: string;
@@ -60,18 +65,57 @@ interface DatabaseAdapterCapabilities {
60
65
  createMigrator?: () => Migrator;
61
66
  generateSchema?: SchemaGenerator;
62
67
  }
63
- type DatabaseAdapterWithCapabilities<TContext = unknown> = DatabasePlugin<TContext> & DatabaseAdapterCapabilities;
64
- type DatabaseAdapter<TContext = unknown> = DatabaseAdapterWithCapabilities<TContext> | DatabasePlugin<TContext> | DatabasePluginFactory<TContext>;
65
- interface DatabaseAPI<TContext = unknown> {
66
- getBundleById(id: string, context?: HotUpdaterContext<TContext>): Promise<Bundle$1 | null>;
67
- getUpdateInfo(args: GetBundlesArgs, context?: HotUpdaterContext<TContext>): Promise<UpdateInfo | null>;
68
- getAppUpdateInfo(args: GetBundlesArgs, context?: HotUpdaterContext<TContext>): Promise<AppUpdateAvailableInfo | null>;
69
- getChannels(context?: HotUpdaterContext<TContext>): Promise<string[]>;
70
- getBundles(options: DatabaseBundleQueryOptions, context?: HotUpdaterContext<TContext>): Promise<PaginatedResult>;
71
- insertBundle(bundle: Bundle$1, context?: HotUpdaterContext<TContext>): Promise<void>;
72
- updateBundleById(bundleId: string, newBundle: Partial<Bundle$1>, context?: HotUpdaterContext<TContext>): Promise<void>;
73
- deleteBundleById(bundleId: string, context?: HotUpdaterContext<TContext>): Promise<void>;
68
+ type DatabaseAdapterWithCapabilities = DatabasePlugin & DatabaseAdapterCapabilities;
69
+ type DatabasePlugin$1 = DatabaseAdapterWithCapabilities;
70
+ interface DatabaseAPI {
71
+ getBundleById(id: string): Promise<Bundle$1 | null>;
72
+ getReleaseCatalog(input: ReleaseCatalogRequest): Promise<_$_hot_updater_core0.ReleaseCatalog | null>;
73
+ getArtifactInfo(targetBundleId: string, currentBundleId: string): Promise<ArtifactInfo | null>;
74
+ getReleaseById(id: string): Promise<ReleaseRow | null>;
75
+ getReleasesByScope(input: {
76
+ readonly scopeKey: string;
77
+ readonly afterReleaseId?: string;
78
+ readonly limit: number;
79
+ }): Promise<readonly ReleaseRow[]>;
80
+ getReleases(input: {
81
+ readonly afterReleaseId?: string;
82
+ readonly beforeReleaseId?: string;
83
+ readonly bundleId?: string;
84
+ readonly channelId?: string;
85
+ readonly enabled?: boolean;
86
+ readonly platform?: "ios" | "android";
87
+ readonly targetAppVersion?: string;
88
+ readonly limit: number;
89
+ }): Promise<readonly ReleaseRow[]>;
90
+ getReleaseCatalogByScopeKey(scopeKey: string): Promise<ReleaseCatalogRow | null>;
91
+ getReleaseCatalogs(input: {
92
+ readonly afterScopeKey?: string;
93
+ readonly limit: number;
94
+ }): Promise<readonly ReleaseCatalogRow[]>;
95
+ updateReleasePolicy(input: {
96
+ readonly expectedRevision?: number;
97
+ readonly patch: ReleasePolicyPatch;
98
+ readonly releaseId: string;
99
+ }): Promise<ReleaseCatalogMutationResult>;
100
+ preflightReleasePolicy(input: {
101
+ readonly expectedRevision?: number;
102
+ readonly patch: ReleasePolicyPatch;
103
+ readonly releaseId: string;
104
+ }): Promise<ReleaseCatalogMutationPreflight>;
105
+ deleteRelease(input: {
106
+ readonly expectedRevision?: number;
107
+ readonly releaseId: string;
108
+ }): Promise<ReleaseCatalogMutationResult>;
109
+ rebuildReleaseCatalog(scopeKey: string): Promise<ReleaseCatalogRebuildResult>;
110
+ commitDatabase(input: DatabaseCommit): Promise<DatabaseCommitResult>;
111
+ getChannels(): Promise<readonly ChannelRow[]>;
112
+ insertChannel(input: ChannelInsertInput): Promise<ChannelInsertResult>;
113
+ deleteChannel(input: ChannelDeleteInput): Promise<ChannelDeleteResult>;
114
+ getBundles(options: _$_hot_updater_plugin_core0.DatabaseBundleQueryOptions): Promise<PaginatedResult>;
115
+ insertBundle(bundle: Bundle$1): Promise<void>;
116
+ insertBundles(bundles: readonly Bundle$1[]): Promise<void>;
117
+ updateBundleById(bundleId: string, newBundle: Partial<Bundle$1>): Promise<void>;
118
+ deleteBundleById(bundleId: string): Promise<void>;
74
119
  }
75
- type StoragePluginFactory<TContext = unknown> = () => RuntimeStoragePlugin<TContext>;
76
120
  //#endregion
77
- export { DatabaseAPI, DatabaseAdapter, DatabasePluginFactory, Migrator, ORMProvider, ORMSQLProvider, RelationMode, SchemaGenerator, StoragePluginFactory };
121
+ export { DatabaseAPI, DatabaseAdapterWithCapabilities, DatabasePlugin$1 as DatabasePlugin, Migrator, ORMProvider, ORMSQLProvider, RelationMode, SchemaGenerator };
package/dist/db/types.mjs CHANGED
@@ -8,15 +8,12 @@ const sqlProviders = [
8
8
  ];
9
9
  const noSqlProviders = ["mongodb"];
10
10
  [...sqlProviders, ...noSqlProviders];
11
- function isDatabasePluginFactory(adapter) {
12
- return typeof adapter === "function";
13
- }
14
- function isDatabasePlugin(adapter) {
15
- return typeof adapter === "object" && adapter !== null && "getBundleById" in adapter && "getBundles" in adapter && "getChannels" in adapter;
11
+ function isDatabasePlugin(plugin) {
12
+ return typeof plugin === "object" && plugin !== null && "name" in plugin && typeof plugin.name === "string" && "models" in plugin && typeof plugin.models === "object" && plugin.models !== null && "bundles" in plugin.models && typeof plugin.models.bundles === "object" && plugin.models.bundles !== null && "findById" in plugin.models.bundles && typeof plugin.models.bundles.findById === "function" && "findMany" in plugin.models.bundles && typeof plugin.models.bundles.findMany === "function" && "count" in plugin.models.bundles && typeof plugin.models.bundles.count === "function" && "bundlePatches" in plugin.models && typeof plugin.models.bundlePatches === "object" && plugin.models.bundlePatches !== null && "findByBundleIds" in plugin.models.bundlePatches && typeof plugin.models.bundlePatches.findByBundleIds === "function" && "channels" in plugin.models && typeof plugin.models.channels === "object" && plugin.models.channels !== null && "insert" in plugin.models.channels && typeof plugin.models.channels.insert === "function" && "list" in plugin.models.channels && typeof plugin.models.channels.list === "function" && "delete" in plugin.models.channels && typeof plugin.models.channels.delete === "function" && "analytics" in plugin.models && typeof plugin.models.analytics === "object" && plugin.models.analytics !== null && "append" in plugin.models.analytics && typeof plugin.models.analytics.append === "function" && "scan" in plugin.models.analytics && typeof plugin.models.analytics.scan === "function" && "apiKeys" in plugin.models && typeof plugin.models.apiKeys === "object" && plugin.models.apiKeys !== null && "create" in plugin.models.apiKeys && typeof plugin.models.apiKeys.create === "function" && "findByHash" in plugin.models.apiKeys && typeof plugin.models.apiKeys.findByHash === "function" && "list" in plugin.models.apiKeys && typeof plugin.models.apiKeys.list === "function" && "revoke" in plugin.models.apiKeys && typeof plugin.models.apiKeys.revoke === "function" && "commit" in plugin && typeof plugin.commit === "function" && (!("dispose" in plugin) || plugin.dispose === void 0 || typeof plugin.dispose === "function");
16
13
  }
17
14
  function getSQLProvider(provider) {
18
15
  if (!provider) return;
19
16
  return sqlProviders.includes(provider) ? provider : void 0;
20
17
  }
21
18
  //#endregion
22
- export { getSQLProvider, isDatabasePlugin, isDatabasePluginFactory };
19
+ export { getSQLProvider, isDatabasePlugin };
@@ -3,6 +3,19 @@ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
3
3
  let _hot_updater_core = require("@hot-updater/core");
4
4
  //#region src/db/updateArtifacts.ts
5
5
  const HBC_ASSET_PATH_RE = /\.bundle$/;
6
+ const asByteSize = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
7
+ const sumByteSizes = (byteSizes) => {
8
+ let total = 0;
9
+ for (const byteSize of byteSizes) {
10
+ if (byteSize === null || total > Number.MAX_SAFE_INTEGER - byteSize) return null;
11
+ total += byteSize;
12
+ }
13
+ return total;
14
+ };
15
+ const shouldUseArchive = (targetBundle, downloadByteSize) => {
16
+ const archiveByteSize = asByteSize(targetBundle.archiveByteSize);
17
+ return archiveByteSize !== null && downloadByteSize !== null && downloadByteSize >= archiveByteSize;
18
+ };
6
19
  const resolveUniqueHbcAssetPath = (manifest) => {
7
20
  const candidates = Object.keys(manifest.assets).sort((left, right) => left.localeCompare(right)).filter((candidate) => HBC_ASSET_PATH_RE.test(candidate));
8
21
  return candidates.length === 1 ? candidates[0] : null;
@@ -18,19 +31,8 @@ const isBundleManifest = (value) => {
18
31
  return typeof manifestAsset.fileHash === "string" && (manifestAsset.signature === void 0 || typeof manifestAsset.signature === "string");
19
32
  });
20
33
  };
21
- const parseBundleMetadata = (value) => {
22
- if (!value) return;
23
- let parsedValue = value;
24
- if (typeof parsedValue === "string") try {
25
- parsedValue = JSON.parse(parsedValue);
26
- } catch {
27
- return;
28
- }
29
- if (!parsedValue || typeof parsedValue !== "object" || Array.isArray(parsedValue)) return;
30
- return (0, _hot_updater_core.stripBundleArtifactMetadata)(parsedValue);
31
- };
32
- async function fetchBundleManifest(storageUri, readStorageText, resolveFileUrl, context) {
33
- const [storageText, fileUrl] = await Promise.all([readStorageText(storageUri, context), resolveFileUrl(storageUri, context)]);
34
+ async function fetchBundleManifest(storageUri, readStorageText) {
35
+ const storageText = await readStorageText(storageUri);
34
36
  if (storageText === null) return null;
35
37
  let payload;
36
38
  try {
@@ -39,89 +41,141 @@ async function fetchBundleManifest(storageUri, readStorageText, resolveFileUrl,
39
41
  return null;
40
42
  }
41
43
  if (!isBundleManifest(payload)) return null;
42
- if (!fileUrl) return null;
43
44
  return {
44
- fileUrl,
45
+ byteSize: asByteSize(new TextEncoder().encode(storageText).byteLength),
45
46
  manifest: payload
46
47
  };
47
48
  }
48
- async function resolveChangedAssets({ assetBaseStorageUri, currentManifest, currentBundle, resolveFileUrl, targetBundle, targetManifest, context }) {
49
- const patchDescriptor = await resolveHbcPatchDescriptor({
49
+ function resolveHbcPatchPlan({ currentBundle, targetBundle, targetManifest }) {
50
+ const matchingPatch = currentBundle ? (0, _hot_updater_core.getBundlePatch)(targetBundle, currentBundle.id) : null;
51
+ const patchAssetPath = resolveUniqueHbcAssetPath(targetManifest);
52
+ if (!currentBundle || !matchingPatch || !patchAssetPath || !matchingPatch.patchStorageUri || !matchingPatch.patchFileHash || !matchingPatch.baseFileHash) return null;
53
+ return {
54
+ assetPath: patchAssetPath,
55
+ patch: {
56
+ baseBundleId: matchingPatch.baseBundleId,
57
+ baseFileHash: matchingPatch.baseFileHash,
58
+ byteSize: asByteSize(matchingPatch.byteSize),
59
+ patchFileHash: matchingPatch.patchFileHash,
60
+ storageUri: matchingPatch.patchStorageUri
61
+ }
62
+ };
63
+ }
64
+ function createManifestArtifactPlan({ assetBaseStorageUri, currentManifest, currentBundle, targetBundle, targetManifest, targetManifestByteSize }) {
65
+ const patchCandidate = resolveHbcPatchPlan({
50
66
  currentBundle,
51
- resolveFileUrl,
52
67
  targetBundle,
53
- targetManifest,
54
- context
68
+ targetManifest
55
69
  });
56
- const changedEntries = await Promise.all(Object.entries(targetManifest.assets).map(async ([assetPath, asset]) => {
57
- if ((currentManifest?.assets[assetPath])?.fileHash === asset.fileHash) return null;
70
+ const changedAssets = Object.entries(targetManifest.assets).flatMap(([assetPath, asset]) => {
71
+ if ((currentManifest?.assets[assetPath])?.fileHash === asset.fileHash) return [];
72
+ const downloadByteSize = asByteSize(asset.downloadByteSize);
58
73
  const downloadPath = (0, _hot_updater_plugin_core.getManifestAssetDownloadPath)(assetPath);
59
- const usesBrotliAsset = downloadPath !== assetPath;
60
- const storageUri = (0, _hot_updater_plugin_core.resolveManifestAssetStorageUri)({
61
- assetBaseStorageUri,
62
- assetPath: downloadPath,
63
- fileHash: asset.fileHash
64
- });
65
- const patch = patchDescriptor?.assetPath === assetPath ? patchDescriptor.patch : null;
74
+ const isTransformedDownload = downloadPath !== assetPath;
75
+ const hasValidDownloadFileHash = (0, _hot_updater_plugin_core.isContentAddressedAssetFileHash)(asset.downloadFileHash);
76
+ const file = {
77
+ byteSize: downloadByteSize !== null && (hasValidDownloadFileHash || !isTransformedDownload && asset.downloadFileHash === void 0) ? downloadByteSize : null,
78
+ storageUri: (0, _hot_updater_plugin_core.resolveManifestAssetStorageUri)({
79
+ assetBaseStorageUri,
80
+ assetPath: downloadPath,
81
+ downloadFileHash: asset.downloadFileHash,
82
+ fileHash: asset.fileHash
83
+ })
84
+ };
85
+ if (isTransformedDownload) file.compression = "br";
86
+ const patch = patchCandidate?.assetPath === assetPath ? patchCandidate.patch : null;
87
+ return [{
88
+ assetPath,
89
+ file,
90
+ fileHash: asset.fileHash,
91
+ patch
92
+ }];
93
+ });
94
+ const allPossibleByteSizesKnown = targetManifestByteSize !== null && changedAssets.every((asset) => asset.file.byteSize !== null && (asset.patch === null || asset.patch.byteSize !== null));
95
+ const primaryByteSizes = changedAssets.map((asset) => {
96
+ if (!asset.patch) return asset.file.byteSize;
97
+ if (asset.patch.byteSize === null || asset.file.byteSize === null) return null;
98
+ return Math.min(asset.patch.byteSize, asset.file.byteSize);
99
+ });
100
+ return {
101
+ allPossibleByteSizesKnown,
102
+ changedAssets,
103
+ manifestByteSize: targetManifestByteSize,
104
+ minimumDownloadByteSize: allPossibleByteSizesKnown ? sumByteSizes([targetManifestByteSize, ...primaryByteSizes]) : null
105
+ };
106
+ }
107
+ async function resolveChangedAssets(plan, resolveFileUrl) {
108
+ const patchAsset = plan.changedAssets.find((asset) => asset.patch !== null);
109
+ let resolvedPatch = null;
110
+ if (patchAsset?.patch) {
111
+ const patchUrl = await resolveFileUrl(patchAsset.patch.storageUri);
112
+ if (patchUrl) resolvedPatch = {
113
+ assetPath: patchAsset.assetPath,
114
+ patch: {
115
+ algorithm: "bsdiff",
116
+ baseBundleId: patchAsset.patch.baseBundleId,
117
+ baseFileHash: patchAsset.patch.baseFileHash,
118
+ patchFileHash: patchAsset.patch.patchFileHash,
119
+ patchUrl
120
+ }
121
+ };
122
+ }
123
+ const changedEntries = await Promise.all(plan.changedAssets.map(async (asset) => {
124
+ let patch = resolvedPatch?.assetPath === asset.assetPath ? resolvedPatch.patch : null;
66
125
  let fileUrl = null;
67
126
  try {
68
- fileUrl = await resolveFileUrl(storageUri, context);
127
+ fileUrl = await resolveFileUrl(asset.file.storageUri);
69
128
  } catch (error) {
70
129
  if (!patch) throw error;
71
130
  }
72
- if (!fileUrl && !patch) return false;
131
+ if (fileUrl && patch && asset.file.byteSize !== null && asset.patch !== null && asset.patch.byteSize !== null && asset.patch.byteSize >= asset.file.byteSize) patch = null;
132
+ if (!fileUrl && !patch) return null;
73
133
  const changedAsset = { fileHash: asset.fileHash };
74
134
  if (fileUrl) {
75
135
  changedAsset.file = { url: fileUrl };
76
- if (usesBrotliAsset) changedAsset.file.compression = "br";
136
+ if (asset.file.compression) changedAsset.file.compression = asset.file.compression;
77
137
  }
78
138
  if (patch) changedAsset.patch = patch;
79
- return [assetPath, changedAsset];
139
+ return {
140
+ asset: [asset.assetPath, changedAsset],
141
+ primaryByteSize: patch ? asset.patch?.byteSize ?? null : asset.file.byteSize
142
+ };
80
143
  }));
81
- if (changedEntries.some((entry) => entry === false)) return null;
82
- return Object.fromEntries(changedEntries.filter((entry) => entry !== null));
83
- }
84
- async function resolveHbcPatchDescriptor({ currentBundle, resolveFileUrl, targetBundle, targetManifest, context }) {
85
- const matchingPatch = targetBundle && currentBundle ? (0, _hot_updater_core.getBundlePatch)(targetBundle, currentBundle.id) : null;
86
- const patchAssetPath = resolveUniqueHbcAssetPath(targetManifest);
87
- if (!currentBundle || !matchingPatch || !patchAssetPath || !matchingPatch.patchStorageUri || !matchingPatch.patchFileHash || !matchingPatch.baseFileHash) return null;
88
- const patchUrl = await resolveFileUrl(matchingPatch.patchStorageUri, context);
89
- if (!patchUrl) return null;
144
+ if (changedEntries.some((entry) => entry === null)) return null;
145
+ const resolvedEntries = changedEntries.filter((entry) => entry !== null);
90
146
  return {
91
- assetPath: patchAssetPath,
92
- patch: {
93
- algorithm: "bsdiff",
94
- baseBundleId: matchingPatch.baseBundleId,
95
- baseFileHash: matchingPatch.baseFileHash,
96
- patchFileHash: matchingPatch.patchFileHash,
97
- patchUrl
98
- }
147
+ changedAssets: Object.fromEntries(resolvedEntries.map((entry) => entry.asset)),
148
+ primaryByteSizes: resolvedEntries.map((entry) => entry.primaryByteSize)
99
149
  };
100
150
  }
101
- async function resolveManifestArtifacts({ currentBundle, resolveFileUrl, readStorageText, targetBundle, context }) {
151
+ async function resolveManifestArtifacts({ archiveUrlUsable, currentBundle, resolveFileUrl, readStorageText, targetBundle }) {
102
152
  const manifestStorageUri = targetBundle ? (0, _hot_updater_core.getManifestStorageUri)(targetBundle) : null;
103
153
  const manifestFileHash = targetBundle ? (0, _hot_updater_core.getManifestFileHash)(targetBundle) : null;
104
154
  const assetBaseStorageUri = targetBundle ? (0, _hot_updater_core.getAssetBaseStorageUri)(targetBundle) : null;
105
- if (!manifestStorageUri || !manifestFileHash || !assetBaseStorageUri) return null;
155
+ if (!targetBundle || !manifestStorageUri || !manifestFileHash || !assetBaseStorageUri) return null;
106
156
  const currentManifestStorageUri = currentBundle ? (0, _hot_updater_core.getManifestStorageUri)(currentBundle) : null;
107
- const [targetManifestResult, currentManifestResult] = await Promise.all([fetchBundleManifest(manifestStorageUri, readStorageText, resolveFileUrl, context), currentManifestStorageUri ? fetchBundleManifest(currentManifestStorageUri, readStorageText, resolveFileUrl, context) : null]);
157
+ const [targetManifestResult, currentManifestResult] = await Promise.all([fetchBundleManifest(manifestStorageUri, readStorageText), currentManifestStorageUri ? fetchBundleManifest(currentManifestStorageUri, readStorageText) : null]);
108
158
  if (!targetManifestResult) return null;
109
- const changedAssets = await resolveChangedAssets({
159
+ const plan = createManifestArtifactPlan({
110
160
  assetBaseStorageUri,
111
161
  currentManifest: currentManifestResult?.manifest ?? null,
112
162
  currentBundle,
113
- resolveFileUrl,
114
163
  targetBundle,
115
164
  targetManifest: targetManifestResult.manifest,
116
- context
165
+ targetManifestByteSize: targetManifestResult.byteSize
117
166
  });
118
- if (!changedAssets) return null;
167
+ if (archiveUrlUsable && plan.allPossibleByteSizesKnown && shouldUseArchive(targetBundle, plan.minimumDownloadByteSize)) return null;
168
+ const manifestUrl = await resolveFileUrl(manifestStorageUri);
169
+ if (!manifestUrl) return null;
170
+ const resolved = await resolveChangedAssets(plan, resolveFileUrl);
171
+ if (!resolved) return null;
172
+ const resolvedDownloadByteSize = sumByteSizes([plan.manifestByteSize, ...resolved.primaryByteSizes]);
173
+ if (archiveUrlUsable && shouldUseArchive(targetBundle, resolvedDownloadByteSize)) return null;
119
174
  return {
120
- changedAssets,
175
+ changedAssets: resolved.changedAssets,
121
176
  manifestFileHash,
122
- manifestUrl: targetManifestResult.fileUrl
177
+ manifestUrl
123
178
  };
124
179
  }
125
180
  //#endregion
126
- exports.parseBundleMetadata = parseBundleMetadata;
127
181
  exports.resolveManifestArtifacts = resolveManifestArtifacts;