@hot-updater/server 0.30.12 → 0.31.1

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 (165) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +25 -0
  2. package/dist/_virtual/_rolldown/runtime.mjs +6 -0
  3. package/dist/adapters/drizzle.cjs +6 -9
  4. package/dist/adapters/drizzle.d.cts +8 -1
  5. package/dist/adapters/drizzle.d.mts +8 -1
  6. package/dist/adapters/drizzle.mjs +5 -2
  7. package/dist/adapters/kysely.cjs +7 -9
  8. package/dist/adapters/kysely.d.cts +14 -1
  9. package/dist/adapters/kysely.d.mts +14 -1
  10. package/dist/adapters/kysely.mjs +6 -2
  11. package/dist/adapters/mongodb.cjs +7 -9
  12. package/dist/adapters/mongodb.d.cts +9 -1
  13. package/dist/adapters/mongodb.d.mts +9 -1
  14. package/dist/adapters/mongodb.mjs +5 -2
  15. package/dist/adapters/prisma.cjs +6 -9
  16. package/dist/adapters/prisma.d.cts +8 -1
  17. package/dist/adapters/prisma.d.mts +8 -1
  18. package/dist/adapters/prisma.mjs +5 -2
  19. package/dist/db/createBundleDiff.cjs +166 -0
  20. package/dist/db/createBundleDiff.d.cts +20 -0
  21. package/dist/db/createBundleDiff.d.mts +20 -0
  22. package/dist/db/createBundleDiff.mjs +161 -0
  23. package/dist/db/index.cjs +15 -16
  24. package/dist/db/index.d.cts +5 -4
  25. package/dist/db/index.d.mts +5 -4
  26. package/dist/db/index.mjs +14 -16
  27. package/dist/db/ormCore.cjs +173 -65
  28. package/dist/db/ormCore.d.cts +100 -34
  29. package/dist/db/ormCore.d.mts +100 -34
  30. package/dist/db/ormCore.mjs +171 -64
  31. package/dist/db/pluginCore.cjs +37 -3
  32. package/dist/db/pluginCore.mjs +36 -3
  33. package/dist/db/schemaEnhancements.cjs +171 -0
  34. package/dist/db/schemaEnhancements.mjs +167 -0
  35. package/dist/db/types.cjs +6 -0
  36. package/dist/db/types.d.cts +19 -7
  37. package/dist/db/types.d.mts +22 -10
  38. package/dist/db/types.mjs +6 -1
  39. package/dist/db/updateArtifacts.cjs +127 -0
  40. package/dist/db/updateArtifacts.mjs +125 -0
  41. package/dist/handler.cjs +61 -5
  42. package/dist/handler.d.cts +2 -2
  43. package/dist/handler.d.mts +5 -5
  44. package/dist/handler.mjs +59 -5
  45. package/dist/index.cjs +2 -0
  46. package/dist/index.d.cts +3 -2
  47. package/dist/index.d.mts +3 -2
  48. package/dist/index.mjs +2 -1
  49. package/dist/node.d.cts +0 -1
  50. package/dist/node.d.mts +0 -1
  51. package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/_u64.cjs +112 -0
  52. package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/_u64.mjs +108 -0
  53. package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/cryptoNode.cjs +22 -0
  54. package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/cryptoNode.mjs +18 -0
  55. package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/sha3.cjs +219 -0
  56. package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/sha3.mjs +214 -0
  57. package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/utils.cjs +275 -0
  58. package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/utils.mjs +270 -0
  59. package/dist/node_modules/.pnpm/@paralleldrive_cuid2@2.3.1/node_modules/@paralleldrive/cuid2/index.cjs +17 -0
  60. package/dist/node_modules/.pnpm/@paralleldrive_cuid2@2.3.1/node_modules/@paralleldrive/cuid2/index.mjs +13 -0
  61. package/dist/node_modules/.pnpm/@paralleldrive_cuid2@2.3.1/node_modules/@paralleldrive/cuid2/src/index.cjs +69 -0
  62. package/dist/node_modules/.pnpm/@paralleldrive_cuid2@2.3.1/node_modules/@paralleldrive/cuid2/src/index.mjs +65 -0
  63. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/column.cjs +52 -0
  64. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/column.mjs +52 -0
  65. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/entity.cjs +16 -0
  66. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/entity.mjs +15 -0
  67. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/pg-core/columns/enum.cjs +7 -0
  68. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/pg-core/columns/enum.mjs +7 -0
  69. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/sql/expressions/conditions.cjs +92 -0
  70. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/sql/expressions/conditions.mjs +78 -0
  71. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/sql/expressions/select.cjs +11 -0
  72. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/sql/expressions/select.mjs +10 -0
  73. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/sql/sql.cjs +383 -0
  74. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/sql/sql.mjs +366 -0
  75. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/subquery.cjs +17 -0
  76. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/subquery.mjs +17 -0
  77. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/table.cjs +60 -0
  78. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/table.mjs +59 -0
  79. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/table.utils.cjs +4 -0
  80. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/table.utils.mjs +4 -0
  81. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/tracing.cjs +6 -0
  82. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/tracing.mjs +6 -0
  83. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/view-common.cjs +4 -0
  84. package/dist/node_modules/.pnpm/drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pglite@0.2.17_@_31f44b782f9321d71f3ce9d35aa1edf7/node_modules/drizzle-orm/view-common.mjs +4 -0
  85. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/adapters/drizzle/index.cjs +383 -0
  86. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/adapters/drizzle/index.d.cts +12 -0
  87. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/adapters/drizzle/index.d.mts +12 -0
  88. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/adapters/drizzle/index.mjs +383 -0
  89. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/adapters/kysely/index.cjs +4 -0
  90. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/adapters/kysely/index.mjs +5 -0
  91. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/adapters/prisma/index.cjs +339 -0
  92. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/adapters/prisma/index.d.cts +70 -0
  93. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/adapters/prisma/index.d.mts +70 -0
  94. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/adapters/prisma/index.mjs +339 -0
  95. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-7PZK4ONR.cjs +57 -0
  96. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-7PZK4ONR.mjs +56 -0
  97. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-C6OTUURW.cjs +330 -0
  98. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-C6OTUURW.mjs +326 -0
  99. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-CHTIKPQU.cjs +166 -0
  100. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-CHTIKPQU.mjs +163 -0
  101. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-GUE4GMNC.cjs +14 -0
  102. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-GUE4GMNC.mjs +13 -0
  103. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-LHHP6UVP.cjs +24 -0
  104. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-LHHP6UVP.mjs +24 -0
  105. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-LVCPMTAT.cjs +1190 -0
  106. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-LVCPMTAT.mjs +1189 -0
  107. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-PK2W2SQ7.cjs +197 -0
  108. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-PK2W2SQ7.mjs +197 -0
  109. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-ZEQMAIFI.cjs +410 -0
  110. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-ZEQMAIFI.mjs +400 -0
  111. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-ZOCGSAWS.cjs +213 -0
  112. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/chunk-ZOCGSAWS.mjs +212 -0
  113. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/create-tg0451Y_.d.cts +285 -0
  114. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/create-tg0451Y_.d.mts +285 -0
  115. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/index-CMqePMTF.d.cts +45 -0
  116. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/index-CMqePMTF.d.mts +45 -0
  117. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/index.cjs +69 -0
  118. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/index.d.cts +49 -0
  119. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/index.d.mts +49 -0
  120. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/index.mjs +67 -0
  121. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/query/index.d.cts +156 -0
  122. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/query/index.d.mts +156 -0
  123. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/schema/index.cjs +1 -0
  124. package/dist/node_modules/.pnpm/fumadb@0.2.2_drizzle-orm@0.44.7_@cloudflare_workers-types@4.20260313.1_@electric-sql_pg_c72c8c754becd21f6d6662e8fbd28e7f/node_modules/fumadb/dist/schema/index.mjs +2 -0
  125. package/dist/{package.cjs → packages/server/package.cjs} +1 -1
  126. package/dist/{package.mjs → packages/server/package.mjs} +1 -1
  127. package/dist/runtime.cjs +13 -13
  128. package/dist/runtime.d.cts +4 -4
  129. package/dist/runtime.d.mts +4 -4
  130. package/dist/runtime.mjs +12 -13
  131. package/dist/schema/v0_21_0.cjs +16 -15
  132. package/dist/schema/v0_21_0.mjs +3 -2
  133. package/dist/schema/v0_29_0.cjs +18 -17
  134. package/dist/schema/v0_29_0.mjs +3 -2
  135. package/dist/schema/v0_31_0.cjs +48 -0
  136. package/dist/schema/v0_31_0.mjs +48 -0
  137. package/dist/storageAccess.cjs +44 -0
  138. package/dist/storageAccess.mjs +44 -0
  139. package/dist/version.cjs +1 -1
  140. package/dist/version.mjs +1 -1
  141. package/package.json +15 -7
  142. package/src/adapters/drizzle.ts +15 -1
  143. package/src/adapters/kysely.ts +24 -1
  144. package/src/adapters/mongodb.ts +19 -1
  145. package/src/adapters/prisma.ts +15 -1
  146. package/src/db/createBundleDiff.spec.ts +402 -0
  147. package/src/db/createBundleDiff.ts +375 -0
  148. package/src/db/index.spec.ts +528 -27
  149. package/src/db/index.ts +22 -36
  150. package/src/db/ormCore.ts +308 -75
  151. package/src/db/pluginCore.spec.ts +385 -0
  152. package/src/db/pluginCore.ts +45 -4
  153. package/src/db/schemaEnhancements.ts +460 -0
  154. package/src/db/types.ts +38 -7
  155. package/src/db/updateArtifacts.ts +388 -0
  156. package/src/handler-standalone.integration.spec.ts +1 -0
  157. package/src/handler.spec.ts +121 -0
  158. package/src/handler.ts +117 -5
  159. package/src/runtime.spec.ts +287 -55
  160. package/src/runtime.ts +21 -37
  161. package/src/schema/v0_21_0.ts +1 -1
  162. package/src/schema/v0_29_0.ts +1 -1
  163. package/src/schema/v0_31_0.ts +58 -0
  164. package/src/storageAccess.spec.ts +57 -0
  165. package/src/storageAccess.ts +90 -0
package/src/handler.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type {
2
+ AppUpdateAvailableInfo,
2
3
  AppUpdateInfo,
3
4
  AppVersionGetBundlesArgs,
4
5
  Bundle,
@@ -9,6 +10,7 @@ import type {
9
10
  DatabaseBundleQueryOptions,
10
11
  HotUpdaterContext,
11
12
  } from "@hot-updater/plugin-core";
13
+ import semver from "semver";
12
14
 
13
15
  import { addRoute, createRouter, findRoute } from "./internalRouter";
14
16
  import type { ChannelsResponse, PaginatedResult } from "./types";
@@ -19,7 +21,7 @@ export interface HandlerAPI<TContext = unknown> {
19
21
  getAppUpdateInfo: (
20
22
  args: AppVersionGetBundlesArgs | FingerprintGetBundlesArgs,
21
23
  context?: HotUpdaterContext<TContext>,
22
- ) => Promise<AppUpdateInfo | null>;
24
+ ) => Promise<AppUpdateAvailableInfo | null>;
23
25
  getBundleById: (
24
26
  id: string,
25
27
  context?: HotUpdaterContext<TContext>,
@@ -88,6 +90,37 @@ class HandlerBadRequestError extends Error {
88
90
  }
89
91
  }
90
92
 
93
+ const SDK_VERSION_HEADER = "Hot-Updater-SDK-Version";
94
+ const EXPLICIT_NO_UPDATE_MIN_SDK_VERSION = "0.31.0";
95
+
96
+ const supportsExplicitNoUpdateResponse = (request: Request) => {
97
+ const sdkVersion = request.headers.get(SDK_VERSION_HEADER)?.trim();
98
+ if (!sdkVersion) {
99
+ return false;
100
+ }
101
+
102
+ const normalizedSdkVersion = semver.valid(sdkVersion);
103
+ return (
104
+ normalizedSdkVersion !== null &&
105
+ semver.gte(normalizedSdkVersion, EXPLICIT_NO_UPDATE_MIN_SDK_VERSION)
106
+ );
107
+ };
108
+
109
+ const serializeUpdateInfo = (
110
+ updateInfo: AppUpdateAvailableInfo | null,
111
+ request: Request,
112
+ ): string => {
113
+ if (updateInfo) {
114
+ return JSON.stringify(updateInfo satisfies AppUpdateInfo);
115
+ }
116
+
117
+ if (supportsExplicitNoUpdateResponse(request)) {
118
+ return JSON.stringify({ status: "UP_TO_DATE" } satisfies AppUpdateInfo);
119
+ }
120
+
121
+ return JSON.stringify(null);
122
+ };
123
+
91
124
  // Route handlers
92
125
  const handleVersion: RouteHandler = async () => {
93
126
  return new Response(JSON.stringify({ version: HOT_UPDATER_SERVER_VERSION }), {
@@ -121,6 +154,43 @@ const requireRouteParam = (
121
154
  return value;
122
155
  };
123
156
 
157
+ const parseBooleanSearchParam = (
158
+ url: URL,
159
+ key: string,
160
+ ): boolean | undefined => {
161
+ const value = url.searchParams.get(key);
162
+ if (value === null) {
163
+ return undefined;
164
+ }
165
+ if (value === "true") {
166
+ return true;
167
+ }
168
+ if (value === "false") {
169
+ return false;
170
+ }
171
+
172
+ throw new HandlerBadRequestError(
173
+ `The '${key}' query parameter must be 'true' or 'false'.`,
174
+ );
175
+ };
176
+
177
+ const parseNullableStringSearchParam = (
178
+ url: URL,
179
+ key: string,
180
+ ): string | null | undefined => {
181
+ const value = url.searchParams.get(key);
182
+ if (value === null) {
183
+ return undefined;
184
+ }
185
+
186
+ return value === "null" ? null : value;
187
+ };
188
+
189
+ const parseStringArraySearchParam = (url: URL, key: string) => {
190
+ const values = url.searchParams.getAll(key);
191
+ return values.length > 0 ? values : undefined;
192
+ };
193
+
124
194
  const requirePlatformParam = (params: Record<string, string>): Platform => {
125
195
  const platform = requireRouteParam(params, "platform");
126
196
 
@@ -156,7 +226,7 @@ const requireBundlePatchPayload = (
156
226
 
157
227
  const handleFingerprintUpdateWithCohort: RouteHandler = async (
158
228
  params,
159
- _request,
229
+ request,
160
230
  api,
161
231
  context,
162
232
  ) => {
@@ -179,7 +249,7 @@ const handleFingerprintUpdateWithCohort: RouteHandler = async (
179
249
  context,
180
250
  );
181
251
 
182
- return new Response(JSON.stringify(updateInfo), {
252
+ return new Response(serializeUpdateInfo(updateInfo, request), {
183
253
  status: 200,
184
254
  headers: { "Content-Type": "application/json" },
185
255
  });
@@ -187,7 +257,7 @@ const handleFingerprintUpdateWithCohort: RouteHandler = async (
187
257
 
188
258
  const handleAppVersionUpdateWithCohort: RouteHandler = async (
189
259
  params,
190
- _request,
260
+ request,
191
261
  api,
192
262
  context,
193
263
  ) => {
@@ -210,7 +280,7 @@ const handleAppVersionUpdateWithCohort: RouteHandler = async (
210
280
  context,
211
281
  );
212
282
 
213
- return new Response(JSON.stringify(updateInfo), {
283
+ return new Response(serializeUpdateInfo(updateInfo, request), {
214
284
  status: 200,
215
285
  headers: { "Content-Type": "application/json" },
216
286
  });
@@ -252,6 +322,29 @@ const handleGetBundles: RouteHandler = async (
252
322
  const offset = url.searchParams.get("offset");
253
323
  const after = url.searchParams.get("after") ?? undefined;
254
324
  const before = url.searchParams.get("before") ?? undefined;
325
+ const enabled = parseBooleanSearchParam(url, "enabled");
326
+ const targetAppVersion = parseNullableStringSearchParam(
327
+ url,
328
+ "targetAppVersion",
329
+ );
330
+ const targetAppVersionIn = parseStringArraySearchParam(
331
+ url,
332
+ "targetAppVersionIn",
333
+ );
334
+ const targetAppVersionNotNull = parseBooleanSearchParam(
335
+ url,
336
+ "targetAppVersionNotNull",
337
+ );
338
+ const fingerprintHash = parseNullableStringSearchParam(
339
+ url,
340
+ "fingerprintHash",
341
+ );
342
+ const idEq = url.searchParams.get("idEq") ?? undefined;
343
+ const idGt = url.searchParams.get("idGt") ?? undefined;
344
+ const idGte = url.searchParams.get("idGte") ?? undefined;
345
+ const idLt = url.searchParams.get("idLt") ?? undefined;
346
+ const idLte = url.searchParams.get("idLte") ?? undefined;
347
+ const idIn = parseStringArraySearchParam(url, "idIn");
255
348
  const page =
256
349
  pageParam === null
257
350
  ? undefined
@@ -282,6 +375,25 @@ const handleGetBundles: RouteHandler = async (
282
375
  where: {
283
376
  ...(channel && { channel }),
284
377
  ...(platform && { platform }),
378
+ ...(enabled !== undefined && { enabled }),
379
+ ...(idEq || idGt || idGte || idLt || idLte || (idIn && idIn.length > 0)
380
+ ? {
381
+ id: {
382
+ ...(idEq && { eq: idEq }),
383
+ ...(idGt && { gt: idGt }),
384
+ ...(idGte && { gte: idGte }),
385
+ ...(idLt && { lt: idLt }),
386
+ ...(idLte && { lte: idLte }),
387
+ ...(idIn && idIn.length > 0 && { in: idIn }),
388
+ },
389
+ }
390
+ : {}),
391
+ ...(targetAppVersion !== undefined && { targetAppVersion }),
392
+ ...(targetAppVersionIn && { targetAppVersionIn }),
393
+ ...(targetAppVersionNotNull !== undefined && {
394
+ targetAppVersionNotNull,
395
+ }),
396
+ ...(fingerprintHash !== undefined && { fingerprintHash }),
285
397
  },
286
398
  limit,
287
399
  page,
@@ -3,7 +3,8 @@ import { NIL_UUID } from "@hot-updater/core";
3
3
  import type {
4
4
  DatabasePlugin,
5
5
  RequestEnvContext,
6
- StoragePlugin,
6
+ RuntimeStoragePlugin,
7
+ RuntimeStorageProfile,
7
8
  } from "@hot-updater/plugin-core";
8
9
  import { createDatabasePlugin } from "@hot-updater/plugin-core";
9
10
  import { describe, expect, expectTypeOf, it, vi } from "vitest";
@@ -31,7 +32,71 @@ type TestEnv = {
31
32
 
32
33
  type TestContext = RequestEnvContext<TestEnv>;
33
34
 
35
+ const createRuntimeStorage = (
36
+ getDownloadUrl: RuntimeStorageProfile<TestContext>["getDownloadUrl"],
37
+ readText: RuntimeStorageProfile<TestContext>["readText"] = async () => null,
38
+ ): RuntimeStoragePlugin<TestContext> => ({
39
+ name: "testStorage",
40
+ supportedProtocol: "s3",
41
+ profiles: {
42
+ runtime: {
43
+ getDownloadUrl,
44
+ readText,
45
+ },
46
+ },
47
+ });
48
+
34
49
  describe("runtime createHotUpdater", () => {
50
+ it("requires storages to implement the runtime profile", () => {
51
+ const database: DatabasePlugin<TestContext> = {
52
+ name: "testDatabase",
53
+ async appendBundle() {},
54
+ async commitBundle() {},
55
+ async deleteBundle() {},
56
+ async getBundleById() {
57
+ return null;
58
+ },
59
+ async getBundles() {
60
+ return {
61
+ data: [],
62
+ pagination: {
63
+ currentPage: 1,
64
+ hasNextPage: false,
65
+ hasPreviousPage: false,
66
+ total: 0,
67
+ totalPages: 0,
68
+ },
69
+ };
70
+ },
71
+ async getChannels() {
72
+ return [];
73
+ },
74
+ async updateBundle() {},
75
+ };
76
+ const nodeOnlyStorage = {
77
+ name: "nodeOnlyStorage",
78
+ supportedProtocol: "s3",
79
+ profiles: {
80
+ node: {
81
+ delete: vi.fn(),
82
+ downloadFile: vi.fn(),
83
+ upload: vi.fn(),
84
+ },
85
+ },
86
+ };
87
+
88
+ expect(() =>
89
+ createHotUpdater({
90
+ database,
91
+ storages: [
92
+ nodeOnlyStorage as unknown as RuntimeStoragePlugin<TestContext>,
93
+ ],
94
+ }),
95
+ ).toThrow(
96
+ 'nodeOnlyStorage does not implement the runtime storage profile for protocol "s3".',
97
+ );
98
+ });
99
+
35
100
  it("resolves storage URLs with handler context when database fast-path is used", async () => {
36
101
  const request = new Request(
37
102
  "https://updates.example.com/api/check-update/app-version/ios/1.0.0/production/" +
@@ -48,13 +113,13 @@ describe("runtime createHotUpdater", () => {
48
113
  status: "UPDATE",
49
114
  storageUri: bundle.storageUri,
50
115
  }));
51
- const getDownloadUrl = vi.fn<StoragePlugin<TestContext>["getDownloadUrl"]>(
52
- async (_storageUri, context) => {
53
- return {
54
- fileUrl: new URL("/bundle.zip", context?.env?.assetHost).toString(),
55
- };
56
- },
57
- );
116
+ const getDownloadUrl = vi.fn<
117
+ RuntimeStorageProfile<TestContext>["getDownloadUrl"]
118
+ >(async (_storageUri, context) => {
119
+ return {
120
+ fileUrl: new URL("/bundle.zip", context?.env?.assetHost).toString(),
121
+ };
122
+ });
58
123
 
59
124
  const database: DatabasePlugin<TestContext> = {
60
125
  name: "testDatabase",
@@ -72,15 +137,7 @@ describe("runtime createHotUpdater", () => {
72
137
  async onUnmount() {},
73
138
  async updateBundle() {},
74
139
  };
75
- const storage: StoragePlugin<TestContext> = {
76
- name: "testStorage",
77
- supportedProtocol: "s3",
78
- async upload(key) {
79
- return { storageUri: `s3://test-bucket/${key}` };
80
- },
81
- async delete() {},
82
- getDownloadUrl,
83
- };
140
+ const storage = createRuntimeStorage(getDownloadUrl);
84
141
 
85
142
  const hotUpdater = createHotUpdater({
86
143
  database,
@@ -156,13 +213,13 @@ describe("runtime createHotUpdater", () => {
156
213
  };
157
214
  },
158
215
  );
159
- const getDownloadUrl = vi.fn<StoragePlugin<TestContext>["getDownloadUrl"]>(
160
- async (_storageUri, context) => {
161
- return {
162
- fileUrl: new URL("/bundle.zip", context?.env?.assetHost).toString(),
163
- };
164
- },
165
- );
216
+ const getDownloadUrl = vi.fn<
217
+ RuntimeStorageProfile<TestContext>["getDownloadUrl"]
218
+ >(async (_storageUri, context) => {
219
+ return {
220
+ fileUrl: new URL("/bundle.zip", context?.env?.assetHost).toString(),
221
+ };
222
+ });
166
223
 
167
224
  const database: DatabasePlugin<TestContext> = {
168
225
  name: "testDatabase",
@@ -179,15 +236,7 @@ describe("runtime createHotUpdater", () => {
179
236
  async onUnmount() {},
180
237
  async updateBundle() {},
181
238
  };
182
- const storage: StoragePlugin<TestContext> = {
183
- name: "testStorage",
184
- supportedProtocol: "s3",
185
- async upload(key) {
186
- return { storageUri: `s3://test-bucket/${key}` };
187
- },
188
- async delete() {},
189
- getDownloadUrl,
190
- };
239
+ const storage = createRuntimeStorage(getDownloadUrl);
191
240
 
192
241
  const hotUpdater = createHotUpdater({
193
242
  database,
@@ -239,6 +288,205 @@ describe("runtime createHotUpdater", () => {
239
288
  );
240
289
  });
241
290
 
291
+ it("returns bsdiff patch metadata when the full asset fallback URL is unavailable", async () => {
292
+ const currentManifestStorageUri =
293
+ "s3://test-bucket/releases/00000000-0000-0000-0000-000000000001/manifest.json";
294
+ const nextManifestStorageUri =
295
+ "s3://test-bucket/releases/00000000-0000-0000-0000-000000000002/manifest.json";
296
+ const currentBundle: Bundle = {
297
+ ...bundle,
298
+ id: "00000000-0000-0000-0000-000000000001",
299
+ assetBaseStorageUri:
300
+ "s3://test-bucket/releases/00000000-0000-0000-0000-000000000001/files",
301
+ manifestFileHash: "sig:current-manifest",
302
+ manifestStorageUri: currentManifestStorageUri,
303
+ storageUri:
304
+ "s3://test-bucket/releases/00000000-0000-0000-0000-000000000001/bundle.zip",
305
+ };
306
+ const nextBundle: Bundle = {
307
+ ...bundle,
308
+ id: "00000000-0000-0000-0000-000000000002",
309
+ assetBaseStorageUri:
310
+ "s3://test-bucket/releases/00000000-0000-0000-0000-000000000002/files",
311
+ manifestFileHash: "sig:next-manifest",
312
+ manifestStorageUri: nextManifestStorageUri,
313
+ patches: [
314
+ {
315
+ baseBundleId: currentBundle.id,
316
+ baseFileHash: "hash-old-bundle",
317
+ patchFileHash: "hash-bsdiff",
318
+ patchStorageUri:
319
+ "s3://test-bucket/releases/00000000-0000-0000-0000-000000000002/patches/00000000-0000-0000-0000-000000000001/index.ios.bundle.bsdiff",
320
+ },
321
+ ],
322
+ storageUri:
323
+ "s3://test-bucket/releases/00000000-0000-0000-0000-000000000002/bundle.zip",
324
+ };
325
+ const request = new Request(
326
+ "https://updates.example.com/api/check-update/app-version/ios/1.0.0/production/" +
327
+ `${NIL_UUID}/${currentBundle.id}`,
328
+ );
329
+ const getBundles = vi.fn<DatabasePlugin<TestContext>["getBundles"]>(
330
+ async () => ({
331
+ data: [nextBundle],
332
+ pagination: {
333
+ hasNextPage: false,
334
+ hasPreviousPage: false,
335
+ currentPage: 1,
336
+ totalPages: 1,
337
+ total: 1,
338
+ },
339
+ }),
340
+ );
341
+ const getDownloadUrl = vi.fn<
342
+ RuntimeStorageProfile<TestContext>["getDownloadUrl"]
343
+ >(async (storageUri, context) => {
344
+ if (storageUri.endsWith("/files/index.ios.bundle")) {
345
+ throw new Error("full asset fallback is unavailable");
346
+ }
347
+
348
+ const storageUrl = new URL(storageUri);
349
+ return {
350
+ fileUrl: new URL(
351
+ storageUrl.pathname,
352
+ context?.env?.assetHost,
353
+ ).toString(),
354
+ };
355
+ });
356
+ const manifests = new Map([
357
+ [
358
+ currentManifestStorageUri,
359
+ JSON.stringify({
360
+ assets: {
361
+ "assets/logo.png": {
362
+ fileHash: "hash-logo",
363
+ },
364
+ "index.ios.bundle": {
365
+ fileHash: "hash-old-bundle",
366
+ },
367
+ },
368
+ bundleId: currentBundle.id,
369
+ }),
370
+ ],
371
+ [
372
+ nextManifestStorageUri,
373
+ JSON.stringify({
374
+ assets: {
375
+ "assets/logo.png": {
376
+ fileHash: "hash-logo",
377
+ },
378
+ "index.ios.bundle": {
379
+ fileHash: "hash-new-bundle",
380
+ },
381
+ },
382
+ bundleId: nextBundle.id,
383
+ }),
384
+ ],
385
+ ]);
386
+ const readText = vi.fn<RuntimeStorageProfile<TestContext>["readText"]>(
387
+ async (storageUri) => manifests.get(storageUri) ?? null,
388
+ );
389
+ const fetchMock = vi.fn<typeof fetch>(async () => {
390
+ return new Response("manifest fetch should not be used", {
391
+ status: 500,
392
+ });
393
+ });
394
+ vi.stubGlobal("fetch", fetchMock);
395
+
396
+ const database: DatabasePlugin<TestContext> = {
397
+ name: "testDatabase",
398
+ async appendBundle() {},
399
+ async commitBundle() {},
400
+ async deleteBundle() {},
401
+ async getBundleById(id) {
402
+ if (id === currentBundle.id) {
403
+ return currentBundle;
404
+ }
405
+ if (id === nextBundle.id) {
406
+ return nextBundle;
407
+ }
408
+ return null;
409
+ },
410
+ getBundles,
411
+ async getChannels() {
412
+ return ["production"];
413
+ },
414
+ async onUnmount() {},
415
+ async updateBundle() {},
416
+ };
417
+ const storage = createRuntimeStorage(getDownloadUrl, readText);
418
+
419
+ try {
420
+ const hotUpdater = createHotUpdater({
421
+ database,
422
+ storages: [storage],
423
+ basePath: "/api/check-update",
424
+ routes: {
425
+ updateCheck: true,
426
+ bundles: false,
427
+ },
428
+ });
429
+
430
+ const response = await hotUpdater.handler(request, {
431
+ env: {
432
+ assetHost: "https://assets.example.com",
433
+ },
434
+ request,
435
+ });
436
+
437
+ await expect(response.json()).resolves.toEqual({
438
+ changedAssets: {
439
+ "index.ios.bundle": {
440
+ file: {
441
+ compression: "br",
442
+ url: "https://assets.example.com/releases/00000000-0000-0000-0000-000000000002/files/index.ios.bundle.br",
443
+ },
444
+ fileHash: "hash-new-bundle",
445
+ patch: {
446
+ algorithm: "bsdiff",
447
+ baseBundleId: "00000000-0000-0000-0000-000000000001",
448
+ baseFileHash: "hash-old-bundle",
449
+ patchFileHash: "hash-bsdiff",
450
+ patchUrl:
451
+ "https://assets.example.com/releases/00000000-0000-0000-0000-000000000002/patches/00000000-0000-0000-0000-000000000001/index.ios.bundle.bsdiff",
452
+ },
453
+ },
454
+ },
455
+ fileHash: "hash123",
456
+ fileUrl:
457
+ "https://assets.example.com/releases/00000000-0000-0000-0000-000000000002/bundle.zip",
458
+ id: "00000000-0000-0000-0000-000000000002",
459
+ manifestFileHash: "sig:next-manifest",
460
+ manifestUrl:
461
+ "https://assets.example.com/releases/00000000-0000-0000-0000-000000000002/manifest.json",
462
+ message: "Test bundle",
463
+ shouldForceUpdate: false,
464
+ status: "UPDATE",
465
+ });
466
+ expect(readText).toHaveBeenCalledWith(
467
+ nextManifestStorageUri,
468
+ expect.objectContaining({
469
+ env: {
470
+ assetHost: "https://assets.example.com",
471
+ },
472
+ request: expect.any(Request),
473
+ }),
474
+ );
475
+ expect(readText).toHaveBeenCalledWith(
476
+ currentManifestStorageUri,
477
+ expect.objectContaining({
478
+ env: {
479
+ assetHost: "https://assets.example.com",
480
+ },
481
+ request: expect.any(Request),
482
+ }),
483
+ );
484
+ expect(fetchMock).not.toHaveBeenCalled();
485
+ } finally {
486
+ vi.unstubAllGlobals();
487
+ }
488
+ });
489
+
242
490
  it("does not inject the request into context unless explicitly provided", async () => {
243
491
  const getBundles = vi.fn<DatabasePlugin<TestContext>["getBundles"]>(
244
492
  async () => {
@@ -270,17 +518,9 @@ describe("runtime createHotUpdater", () => {
270
518
  async onUnmount() {},
271
519
  async updateBundle() {},
272
520
  };
273
- const storage: StoragePlugin<TestContext> = {
274
- name: "testStorage",
275
- supportedProtocol: "s3",
276
- async upload(key) {
277
- return { storageUri: `s3://test-bucket/${key}` };
278
- },
279
- async delete() {},
280
- async getDownloadUrl() {
281
- return { fileUrl: "https://assets.example.com/bundle.zip" };
282
- },
283
- };
521
+ const storage = createRuntimeStorage(async () => {
522
+ return { fileUrl: "https://assets.example.com/bundle.zip" };
523
+ });
284
524
 
285
525
  const hotUpdater = createHotUpdater({
286
526
  database,
@@ -343,17 +583,9 @@ describe("runtime createHotUpdater", () => {
343
583
  async onUnmount() {},
344
584
  async updateBundle() {},
345
585
  };
346
- const storage: StoragePlugin<TestContext> = {
347
- name: "testStorage",
348
- supportedProtocol: "s3",
349
- async upload(key) {
350
- return { storageUri: `s3://test-bucket/${key}` };
351
- },
352
- async delete() {},
353
- async getDownloadUrl() {
354
- return { fileUrl: "https://assets.example.com/bundle.zip" };
355
- },
356
- };
586
+ const storage = createRuntimeStorage(async () => {
587
+ return { fileUrl: "https://assets.example.com/bundle.zip" };
588
+ });
357
589
 
358
590
  const hotUpdater = createHotUpdater({
359
591
  database,
package/src/runtime.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type {
2
2
  HotUpdaterContext,
3
- StoragePlugin,
3
+ RuntimeStoragePlugin,
4
4
  } from "@hot-updater/plugin-core";
5
+ import { assertRuntimeStoragePlugin } from "@hot-updater/plugin-core";
5
6
 
6
7
  import { createPluginDatabaseCore } from "./db/pluginCore";
7
8
  import {
@@ -13,6 +14,7 @@ import {
13
14
  } from "./db/types";
14
15
  import { createHandler, type HandlerRoutes } from "./handler";
15
16
  import { normalizeBasePath } from "./route";
17
+ import { createStorageAccess } from "./storageAccess";
16
18
 
17
19
  export type HotUpdaterAPI<TContext = unknown> = DatabaseAPI<TContext> & {
18
20
  basePath: string;
@@ -25,8 +27,14 @@ export type HotUpdaterAPI<TContext = unknown> = DatabaseAPI<TContext> & {
25
27
 
26
28
  export interface CreateHotUpdaterOptions<TContext = unknown> {
27
29
  database: DatabaseAdapter<TContext>;
28
- storages?: (StoragePlugin<TContext> | StoragePluginFactory<TContext>)[];
29
- storagePlugins?: (StoragePlugin<TContext> | StoragePluginFactory<TContext>)[];
30
+ storages?: (
31
+ | RuntimeStoragePlugin<TContext>
32
+ | StoragePluginFactory<TContext>
33
+ )[];
34
+ storagePlugins?: (
35
+ | RuntimeStoragePlugin<TContext>
36
+ | StoragePluginFactory<TContext>
37
+ )[];
30
38
  basePath?: string;
31
39
  cwd?: string;
32
40
  routes?: HandlerRoutes;
@@ -38,39 +46,14 @@ export function createHotUpdater<TContext = unknown>(
38
46
  const database = options.database;
39
47
  const basePath = normalizeBasePath(options.basePath ?? "/api");
40
48
  const storagePlugins = (options.storages ?? options.storagePlugins ?? []).map(
41
- (plugin) => (typeof plugin === "function" ? plugin() : plugin),
49
+ (plugin) => {
50
+ const storagePlugin = typeof plugin === "function" ? plugin() : plugin;
51
+ assertRuntimeStoragePlugin(storagePlugin);
52
+ return storagePlugin;
53
+ },
42
54
  );
43
-
44
- const resolveStoragePluginUrl = async (
45
- storageUri: string | null,
46
- context?: HotUpdaterContext<TContext>,
47
- ): Promise<string | null> => {
48
- if (!storageUri) {
49
- return null;
50
- }
51
-
52
- const url = new URL(storageUri);
53
- const protocol = url.protocol.replace(":", "");
54
-
55
- if (protocol === "http" || protocol === "https") {
56
- return storageUri;
57
- }
58
-
59
- const plugin = storagePlugins.find(
60
- (item) => item.supportedProtocol === protocol,
61
- );
62
-
63
- if (!plugin) {
64
- throw new Error(`No storage plugin for protocol: ${protocol}`);
65
- }
66
-
67
- const { fileUrl } = await plugin.getDownloadUrl(storageUri, context);
68
- if (!fileUrl) {
69
- throw new Error("Storage plugin returned empty fileUrl");
70
- }
71
-
72
- return fileUrl;
73
- };
55
+ const { readStorageText, resolveFileUrl } =
56
+ createStorageAccess(storagePlugins);
74
57
 
75
58
  if (!isDatabasePluginFactory(database) && !isDatabasePlugin(database)) {
76
59
  throw new Error(
@@ -81,12 +64,13 @@ export function createHotUpdater<TContext = unknown>(
81
64
  const plugin = isDatabasePluginFactory(database) ? database() : database;
82
65
  const core = createPluginDatabaseCore<TContext>(
83
66
  () => plugin,
84
- resolveStoragePluginUrl,
67
+ resolveFileUrl,
85
68
  isDatabasePluginFactory(database)
86
69
  ? {
87
70
  createMutationPlugin: () => database(),
71
+ readStorageText,
88
72
  }
89
- : undefined,
73
+ : { readStorageText },
90
74
  );
91
75
 
92
76
  const api = {
@@ -11,7 +11,7 @@ export const v0_21_0 = schema({
11
11
  file_hash: column("file_hash", "string"),
12
12
  git_commit_hash: column("git_commit_hash", "string").nullable(),
13
13
  message: column("message", "string").nullable(),
14
- channel: column("channel", "string"),
14
+ channel: column("channel", "string").defaultTo("production"),
15
15
  storage_uri: column("storage_uri", "string"),
16
16
  target_app_version: column("target_app_version", "string").nullable(),
17
17
  fingerprint_hash: column("fingerprint_hash", "string").nullable(),