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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/LICENSE +12 -14
  2. package/dist/adapters/drizzle.cjs +32 -75
  3. package/dist/adapters/drizzle.d.cts +13 -5
  4. package/dist/adapters/drizzle.d.mts +13 -5
  5. package/dist/adapters/drizzle.mjs +32 -77
  6. package/dist/adapters/drizzleExecutor.cjs +114 -0
  7. package/dist/adapters/drizzleExecutor.d.cts +9 -0
  8. package/dist/adapters/drizzleExecutor.d.mts +9 -0
  9. package/dist/adapters/drizzleExecutor.mjs +112 -0
  10. package/dist/adapters/kysely.cjs +22 -31
  11. package/dist/adapters/kysely.d.cts +10 -6
  12. package/dist/adapters/kysely.d.mts +10 -6
  13. package/dist/adapters/kysely.mjs +23 -33
  14. package/dist/adapters/kyselyExecutor.cjs +32 -0
  15. package/dist/adapters/kyselyExecutor.d.cts +11 -0
  16. package/dist/adapters/kyselyExecutor.d.mts +11 -0
  17. package/dist/adapters/kyselyExecutor.mjs +32 -0
  18. package/dist/adapters/mongodb.cjs +18 -54
  19. package/dist/adapters/mongodb.d.cts +10 -5
  20. package/dist/adapters/mongodb.d.mts +10 -5
  21. package/dist/adapters/mongodb.mjs +19 -56
  22. package/dist/adapters/mongodbAdapter.cjs +192 -0
  23. package/dist/adapters/mongodbAdapter.d.cts +9 -0
  24. package/dist/adapters/mongodbAdapter.d.mts +9 -0
  25. package/dist/adapters/mongodbAdapter.mjs +191 -0
  26. package/dist/adapters/prisma.cjs +35 -267
  27. package/dist/adapters/prisma.d.cts +12 -7
  28. package/dist/adapters/prisma.d.mts +12 -7
  29. package/dist/adapters/prisma.mjs +36 -268
  30. package/dist/adapters/prismaExecutor.cjs +63 -0
  31. package/dist/adapters/prismaExecutor.mjs +63 -0
  32. package/dist/adapters/sqlProviders.cjs +14 -0
  33. package/dist/adapters/sqlProviders.mjs +14 -0
  34. package/dist/assembly/assemblePlugins.cjs +144 -0
  35. package/dist/assembly/assemblePlugins.d.cts +5 -0
  36. package/dist/assembly/assemblePlugins.d.mts +5 -0
  37. package/dist/assembly/assemblePlugins.mjs +139 -0
  38. package/dist/assembly/clientPlugins.cjs +88 -0
  39. package/dist/assembly/clientPlugins.mjs +88 -0
  40. package/dist/assembly/configError.d.cts +2 -0
  41. package/dist/assembly/configError.d.mts +2 -0
  42. package/dist/assembly/configError.mjs +2 -0
  43. package/dist/core/api.cjs +51 -0
  44. package/dist/core/api.d.cts +54 -0
  45. package/dist/core/api.d.mts +54 -0
  46. package/dist/core/api.mjs +51 -0
  47. package/dist/core/baseCandidates.cjs +28 -0
  48. package/dist/core/baseCandidates.mjs +28 -0
  49. package/dist/core/operations.cjs +351 -0
  50. package/dist/core/operations.mjs +351 -0
  51. package/dist/core/reads.cjs +273 -0
  52. package/dist/core/reads.d.cts +9 -0
  53. package/dist/core/reads.d.mts +9 -0
  54. package/dist/core/reads.mjs +267 -0
  55. package/dist/core/releases.cjs +193 -0
  56. package/dist/core/releases.mjs +190 -0
  57. package/dist/core/writes.cjs +96 -0
  58. package/dist/core/writes.mjs +91 -0
  59. package/dist/createHotUpdaterCore.cjs +72 -91
  60. package/dist/createHotUpdaterCore.d.cts +106 -38
  61. package/dist/createHotUpdaterCore.d.mts +106 -38
  62. package/dist/createHotUpdaterCore.mjs +74 -89
  63. package/dist/db/engineDrizzleSchema.cjs +53 -0
  64. package/dist/db/engineDrizzleSchema.mjs +53 -0
  65. package/dist/db/enginePrismaSchema.cjs +84 -0
  66. package/dist/db/enginePrismaSchema.d.cts +5 -0
  67. package/dist/db/enginePrismaSchema.d.mts +5 -0
  68. package/dist/db/enginePrismaSchema.mjs +83 -0
  69. package/dist/db/releaseCatalog.cjs +24 -47
  70. package/dist/db/releaseCatalog.mjs +20 -44
  71. package/dist/db/updateArtifacts.cjs +43 -72
  72. package/dist/db/updateArtifacts.mjs +40 -69
  73. package/dist/handler.cjs +59 -43
  74. package/dist/handler.d.cts +3 -5
  75. package/dist/handler.d.mts +3 -5
  76. package/dist/handler.mjs +61 -43
  77. package/dist/handlerAdminRoutes.cjs +374 -0
  78. package/dist/handlerAdminRoutes.mjs +372 -0
  79. package/dist/handlerParameters.cjs +6 -11
  80. package/dist/handlerParameters.mjs +6 -10
  81. package/dist/handlerReleaseCatalogRoutes.cjs +32 -15
  82. package/dist/handlerReleaseCatalogRoutes.mjs +32 -15
  83. package/dist/handlerTypes.d.cts +2 -55
  84. package/dist/handlerTypes.d.mts +2 -55
  85. package/dist/handlerVersionRoutes.cjs +20 -4
  86. package/dist/handlerVersionRoutes.mjs +20 -4
  87. package/dist/index.cjs +9 -9
  88. package/dist/index.d.cts +8 -9
  89. package/dist/index.d.mts +8 -9
  90. package/dist/index.mjs +3 -4
  91. package/dist/node.cjs +3 -6
  92. package/dist/node.d.cts +2 -2
  93. package/dist/node.d.mts +2 -2
  94. package/dist/node.mjs +4 -4
  95. package/dist/package.cjs +1 -1
  96. package/dist/package.mjs +1 -1
  97. package/dist/plugins/api-keys/index.cjs +9 -0
  98. package/dist/plugins/api-keys/index.d.cts +1 -0
  99. package/dist/plugins/api-keys/index.d.mts +1 -0
  100. package/dist/plugins/api-keys/index.mjs +2 -0
  101. package/dist/plugins/definePlugin.d.cts +2 -0
  102. package/dist/plugins/definePlugin.d.mts +2 -0
  103. package/dist/plugins/insights/index.cjs +9 -0
  104. package/dist/plugins/insights/index.d.cts +1 -0
  105. package/dist/plugins/insights/index.d.mts +1 -0
  106. package/dist/plugins/insights/index.mjs +2 -0
  107. package/dist/plugins/official.cjs +30 -0
  108. package/dist/plugins/official.mjs +29 -0
  109. package/dist/storageAccess.cjs +13 -10
  110. package/dist/storageAccess.mjs +13 -10
  111. package/dist/types/index.d.cts +2 -28
  112. package/dist/types/index.d.mts +2 -28
  113. package/package.json +26 -14
  114. package/dist/_virtual/_rolldown/runtime.cjs +0 -23
  115. package/dist/adapters/databaseConstraintErrors.cjs +0 -22
  116. package/dist/adapters/databaseConstraintErrors.mjs +0 -21
  117. package/dist/adapters/databasePluginUtils.cjs +0 -116
  118. package/dist/adapters/databasePluginUtils.mjs +0 -106
  119. package/dist/adapters/drizzleCrud.cjs +0 -311
  120. package/dist/adapters/drizzleCrud.mjs +0 -308
  121. package/dist/adapters/drizzleLazyDB.cjs +0 -106
  122. package/dist/adapters/drizzleLazyDB.mjs +0 -106
  123. package/dist/adapters/drizzleQuery.cjs +0 -69
  124. package/dist/adapters/drizzleQuery.mjs +0 -69
  125. package/dist/adapters/insightsTransaction.cjs +0 -22
  126. package/dist/adapters/insightsTransaction.mjs +0 -22
  127. package/dist/adapters/kyselyCrud.cjs +0 -305
  128. package/dist/adapters/kyselyCrud.mjs +0 -304
  129. package/dist/adapters/kyselyQuery.cjs +0 -56
  130. package/dist/adapters/kyselyQuery.mjs +0 -56
  131. package/dist/adapters/mongodbCollections.cjs +0 -38
  132. package/dist/adapters/mongodbCollections.mjs +0 -32
  133. package/dist/adapters/mongodbQuery.cjs +0 -94
  134. package/dist/adapters/mongodbQuery.mjs +0 -86
  135. package/dist/adapters/mongodbReads.cjs +0 -210
  136. package/dist/adapters/mongodbReads.mjs +0 -210
  137. package/dist/adapters/mongodbWrites.cjs +0 -148
  138. package/dist/adapters/mongodbWrites.mjs +0 -148
  139. package/dist/adapters/prismaQuery.cjs +0 -57
  140. package/dist/adapters/prismaQuery.mjs +0 -56
  141. package/dist/adapters/prismaRows.cjs +0 -219
  142. package/dist/adapters/prismaRows.mjs +0 -209
  143. package/dist/apiKeys.cjs +0 -143
  144. package/dist/apiKeys.d.cts +0 -49
  145. package/dist/apiKeys.d.mts +0 -49
  146. package/dist/apiKeys.mjs +0 -133
  147. package/dist/db/createBundleDiff.cjs +0 -144
  148. package/dist/db/createBundleDiff.d.cts +0 -16
  149. package/dist/db/createBundleDiff.d.mts +0 -16
  150. package/dist/db/createBundleDiff.mjs +0 -141
  151. package/dist/db/databasePluginCore.cjs +0 -137
  152. package/dist/db/databasePluginCore.mjs +0 -137
  153. package/dist/db/fixedMigrator.cjs +0 -79
  154. package/dist/db/fixedMigrator.mjs +0 -78
  155. package/dist/db/fixedMigratorMongo.cjs +0 -321
  156. package/dist/db/fixedMigratorMongo.mjs +0 -321
  157. package/dist/db/fixedMigratorShared.cjs +0 -23
  158. package/dist/db/fixedMigratorShared.mjs +0 -18
  159. package/dist/db/index.cjs +0 -27
  160. package/dist/db/index.d.cts +0 -12
  161. package/dist/db/index.d.mts +0 -12
  162. package/dist/db/index.mjs +0 -22
  163. package/dist/db/mongoMigrationExecution.cjs +0 -11
  164. package/dist/db/mongoMigrationExecution.mjs +0 -11
  165. package/dist/db/releaseCatalog.d.cts +0 -16
  166. package/dist/db/releaseCatalog.d.mts +0 -16
  167. package/dist/db/schema/insightsCollation.cjs +0 -14
  168. package/dist/db/schema/insightsCollation.mjs +0 -14
  169. package/dist/db/schema/mongodb.cjs +0 -25
  170. package/dist/db/schema/mongodb.mjs +0 -25
  171. package/dist/db/schema/registry.cjs +0 -21
  172. package/dist/db/schema/registry.mjs +0 -17
  173. package/dist/db/schema/sql.cjs +0 -105
  174. package/dist/db/schema/sql.mjs +0 -97
  175. package/dist/db/schema/sqlOperations.cjs +0 -27
  176. package/dist/db/schema/sqlOperations.mjs +0 -26
  177. package/dist/db/schemaGenerators.cjs +0 -275
  178. package/dist/db/schemaGenerators.mjs +0 -273
  179. package/dist/db/schemaReadiness.cjs +0 -26
  180. package/dist/db/schemaReadiness.d.cts +0 -9
  181. package/dist/db/schemaReadiness.d.mts +0 -9
  182. package/dist/db/schemaReadiness.mjs +0 -25
  183. package/dist/db/sqlMigrationExecution.cjs +0 -67
  184. package/dist/db/sqlMigrationExecution.mjs +0 -67
  185. package/dist/db/types.cjs +0 -22
  186. package/dist/db/types.d.cts +0 -118
  187. package/dist/db/types.d.mts +0 -118
  188. package/dist/db/types.mjs +0 -19
  189. package/dist/handlerBundleRoutes.cjs +0 -155
  190. package/dist/handlerBundleRoutes.mjs +0 -155
  191. package/dist/handlerReleaseManagementRoutes.cjs +0 -124
  192. package/dist/handlerReleaseManagementRoutes.mjs +0 -124
  193. package/dist/insights/domain.d.cts +0 -89
  194. package/dist/insights/domain.d.mts +0 -89
  195. package/dist/insights/errors.cjs +0 -15
  196. package/dist/insights/errors.mjs +0 -14
  197. package/dist/insights/eventInput.cjs +0 -155
  198. package/dist/insights/eventInput.mjs +0 -153
  199. package/dist/insights/provider.cjs +0 -314
  200. package/dist/insights/provider.d.cts +0 -6
  201. package/dist/insights/provider.d.mts +0 -6
  202. package/dist/insights/provider.mjs +0 -314
  203. package/dist/insights/queryInput.cjs +0 -93
  204. package/dist/insights/queryInput.mjs +0 -91
  205. package/dist/insights/routes.cjs +0 -58
  206. package/dist/insights/routes.mjs +0 -56
  207. package/dist/insights/types.d.cts +0 -32
  208. package/dist/insights/types.d.mts +0 -32
  209. package/dist/schema/dsl.cjs +0 -103
  210. package/dist/schema/dsl.mjs +0 -87
  211. package/dist/schema/index.cjs +0 -20
  212. package/dist/schema/index.mjs +0 -7
  213. package/dist/schema/settings.cjs +0 -9
  214. package/dist/schema/settings.mjs +0 -9
  215. package/dist/schema/types.cjs +0 -8
  216. package/dist/schema/types.mjs +0 -6
  217. package/dist/schema/v1_0_0.cjs +0 -406
  218. package/dist/schema/v1_0_0.mjs +0 -398
  219. package/src/adapters/databaseConstraintErrors.ts +0 -25
  220. package/src/adapters/databasePluginTestDatabase.ts +0 -120
  221. package/src/adapters/databasePluginUtils.spec.ts +0 -29
  222. package/src/adapters/databasePluginUtils.ts +0 -214
  223. package/src/adapters/drizzle.spec.ts +0 -336
  224. package/src/adapters/drizzle.ts +0 -162
  225. package/src/adapters/drizzleCrud.ts +0 -571
  226. package/src/adapters/drizzleLazyDB.ts +0 -271
  227. package/src/adapters/drizzleQuery.ts +0 -164
  228. package/src/adapters/insightsTransaction.ts +0 -32
  229. package/src/adapters/kysely.spec.ts +0 -174
  230. package/src/adapters/kysely.ts +0 -110
  231. package/src/adapters/kyselyCrud.ts +0 -709
  232. package/src/adapters/kyselyQuery.ts +0 -128
  233. package/src/adapters/mongodb.integration.spec.ts +0 -210
  234. package/src/adapters/mongodb.spec.ts +0 -209
  235. package/src/adapters/mongodb.ts +0 -138
  236. package/src/adapters/mongodbCollections.ts +0 -67
  237. package/src/adapters/mongodbQuery.ts +0 -255
  238. package/src/adapters/mongodbReads.ts +0 -380
  239. package/src/adapters/mongodbRows.spec.ts +0 -64
  240. package/src/adapters/mongodbRows.ts +0 -118
  241. package/src/adapters/mongodbTestClient.ts +0 -377
  242. package/src/adapters/mongodbTestFilter.ts +0 -169
  243. package/src/adapters/mongodbWrites.ts +0 -287
  244. package/src/adapters/prisma.spec.ts +0 -293
  245. package/src/adapters/prisma.ts +0 -565
  246. package/src/adapters/prismaQuery.ts +0 -129
  247. package/src/adapters/prismaRows.spec.ts +0 -98
  248. package/src/adapters/prismaRows.ts +0 -337
  249. package/src/adapters/prismaTestClient.ts +0 -413
  250. package/src/apiKeys.integration.spec.ts +0 -192
  251. package/src/apiKeys.spec.ts +0 -162
  252. package/src/apiKeys.ts +0 -220
  253. package/src/calculatePagination.ts +0 -34
  254. package/src/createHotUpdaterCore.ts +0 -246
  255. package/src/db/bundleRows.spec.ts +0 -164
  256. package/src/db/bundleRows.ts +0 -10
  257. package/src/db/createBundleDiff.spec.ts +0 -450
  258. package/src/db/createBundleDiff.ts +0 -364
  259. package/src/db/databasePluginCore.spec.ts +0 -62
  260. package/src/db/databasePluginCore.testFixtures.ts +0 -76
  261. package/src/db/databasePluginCore.ts +0 -185
  262. package/src/db/databasePluginUpdateCheck.bench.ts +0 -110
  263. package/src/db/fixedMigrator.spec.ts +0 -296
  264. package/src/db/fixedMigrator.ts +0 -147
  265. package/src/db/fixedMigratorMongo.spec.ts +0 -239
  266. package/src/db/fixedMigratorMongo.ts +0 -425
  267. package/src/db/fixedMigratorShared.ts +0 -36
  268. package/src/db/hotUpdaterSchema.ts +0 -5
  269. package/src/db/index.spec.ts +0 -1269
  270. package/src/db/index.ts +0 -47
  271. package/src/db/mongoMigrationExecution.ts +0 -23
  272. package/src/db/node-sqlite.d.ts +0 -25
  273. package/src/db/releaseCatalog.ts +0 -148
  274. package/src/db/schema/definitions.ts +0 -1
  275. package/src/db/schema/insightsCollation.ts +0 -21
  276. package/src/db/schema/mongodb.ts +0 -40
  277. package/src/db/schema/registry.ts +0 -55
  278. package/src/db/schema/sql.ts +0 -244
  279. package/src/db/schema/sqlOperations.ts +0 -63
  280. package/src/db/schema/types.ts +0 -1
  281. package/src/db/schemaGenerators.ts +0 -494
  282. package/src/db/schemaReadiness.ts +0 -34
  283. package/src/db/sqlMigrationExecution.spec.ts +0 -65
  284. package/src/db/sqlMigrationExecution.ts +0 -108
  285. package/src/db/types.spec.ts +0 -63
  286. package/src/db/types.ts +0 -228
  287. package/src/db/updateArtifacts.spec.ts +0 -359
  288. package/src/db/updateArtifacts.ts +0 -541
  289. package/src/handler-standalone.integration.spec.ts +0 -528
  290. package/src/handler.spec.ts +0 -190
  291. package/src/handler.testFixtures.ts +0 -30
  292. package/src/handler.ts +0 -245
  293. package/src/handlerAuth.integration.spec.ts +0 -33
  294. package/src/handlerBundleRoutes.ts +0 -259
  295. package/src/handlerErrors.ts +0 -7
  296. package/src/handlerManagement.spec.ts +0 -262
  297. package/src/handlerParameters.ts +0 -105
  298. package/src/handlerReleaseCatalogRoutes.ts +0 -154
  299. package/src/handlerReleaseManagementRoutes.ts +0 -213
  300. package/src/handlerTypes.ts +0 -96
  301. package/src/handlerVersionRoutes.ts +0 -12
  302. package/src/index.ts +0 -30
  303. package/src/insights/domain.ts +0 -103
  304. package/src/insights/errors.ts +0 -11
  305. package/src/insights/eventInput.ts +0 -225
  306. package/src/insights/insights.integration.spec.ts +0 -381
  307. package/src/insights/provider.spec.ts +0 -385
  308. package/src/insights/provider.ts +0 -591
  309. package/src/insights/queryInput.ts +0 -141
  310. package/src/insights/routes.ts +0 -104
  311. package/src/insights/types.ts +0 -55
  312. package/src/internalRouter.ts +0 -104
  313. package/src/node.spec.ts +0 -119
  314. package/src/node.ts +0 -111
  315. package/src/releaseCatalogRoutes.integration.spec.ts +0 -238
  316. package/src/runtime.spec.ts +0 -194
  317. package/src/runtime.testFixtures.ts +0 -71
  318. package/src/schema/dsl-all-versions.spec.ts +0 -37
  319. package/src/schema/dsl.ts +0 -187
  320. package/src/schema/index.ts +0 -10
  321. package/src/schema/settings.ts +0 -15
  322. package/src/schema/types.ts +0 -79
  323. package/src/schema/v1_0_0.spec.ts +0 -220
  324. package/src/schema/v1_0_0.ts +0 -529
  325. package/src/storageAccess.spec.ts +0 -152
  326. package/src/storageAccess.ts +0 -141
  327. package/src/types/index.ts +0 -34
  328. package/src/version.ts +0 -3
@@ -1,529 +0,0 @@
1
- import {
2
- bool,
3
- check,
4
- column,
5
- foreignKey,
6
- float,
7
- idColumn,
8
- index,
9
- integer,
10
- json,
11
- largeString,
12
- relation,
13
- schema,
14
- stringColumn,
15
- table,
16
- uniqueIndex,
17
- uuid,
18
- varchar,
19
- } from "./dsl";
20
- import { createSettingsTable } from "./settings";
21
- import { HOT_UPDATER_SETTINGS_TABLE } from "./types";
22
-
23
- const channelIdentityCollations = {
24
- mysql: "utf8mb4_bin",
25
- mssql: "Latin1_General_100_BIN2_SC",
26
- sqlite: "binary",
27
- } as const;
28
-
29
- const catalogKeyCollations = {
30
- mysql: "ascii_bin",
31
- mssql: "Latin1_General_100_BIN2",
32
- sqlite: "binary",
33
- } as const;
34
-
35
- export const channelsV100 = table(
36
- "channels",
37
- {
38
- id: idColumn("id", varchar(255)).collate(channelIdentityCollations),
39
- name: column("name", varchar(255)).collate(channelIdentityCollations),
40
- },
41
- {
42
- indexes: [uniqueIndex("channels_name_key", ["name"])],
43
- checks: [
44
- check({
45
- name: "channels_id_length_check",
46
- expression: "char_length(id) between 1 and 255",
47
- providerExpressions: {
48
- mssql:
49
- "len(id collate Latin1_General_100_BIN2_SC + N'#') - 1 between 1 and 255",
50
- sqlite: "length(id) between 1 and 255",
51
- },
52
- sqliteInline: true,
53
- }),
54
- check({
55
- name: "channels_name_length_check",
56
- expression: "char_length(name) between 1 and 255",
57
- providerExpressions: {
58
- mssql:
59
- "len(name collate Latin1_General_100_BIN2_SC + N'#') - 1 between 1 and 255",
60
- sqlite: "length(name) between 1 and 255",
61
- },
62
- sqliteInline: true,
63
- }),
64
- ],
65
- },
66
- );
67
-
68
- export const bundlePatchesV100 = table(
69
- "bundle_patches",
70
- {
71
- id: idColumn("id", varchar(255)),
72
- bundle_id: uuid("bundle_id"),
73
- base_bundle_id: uuid("base_bundle_id"),
74
- base_file_hash: column("base_file_hash", "string"),
75
- patch_file_hash: column("patch_file_hash", "string"),
76
- patch_storage_uri: column("patch_storage_uri", "string"),
77
- byte_size: float("byte_size"),
78
- order_index: integer("order_index").defaultTo(0),
79
- },
80
- {
81
- indexes: [
82
- index("bundle_patches_bundle_id_idx", ["bundle_id"]),
83
- index("bundle_patches_base_bundle_id_idx", ["base_bundle_id"]),
84
- ],
85
- foreignKeys: [
86
- foreignKey("bundle_patches_bundle_id_fk", ["bundle_id"], "bundles", [
87
- "id",
88
- ]),
89
- foreignKey(
90
- "bundle_patches_base_bundle_id_fk",
91
- ["base_bundle_id"],
92
- "bundles",
93
- ["id"],
94
- ),
95
- ],
96
- relations: [
97
- relation({
98
- name: "bundle",
99
- fieldName: "patches",
100
- targetFieldName: "bundle",
101
- relationName: "bundle_patches_bundles_patches",
102
- columns: ["bundle_id"],
103
- referencedTable: "bundles",
104
- referencedColumns: ["id"],
105
- }),
106
- relation({
107
- name: "baseBundle",
108
- fieldName: "baseForPatches",
109
- targetFieldName: "baseBundle",
110
- relationName: "bundle_patches_bundles_baseForPatches",
111
- columns: ["base_bundle_id"],
112
- referencedTable: "bundles",
113
- referencedColumns: ["id"],
114
- }),
115
- ],
116
- checks: [
117
- check({
118
- name: "bundle_patches_byte_size_check",
119
- expression: "byte_size >= 0 and byte_size <= 9007199254740991",
120
- sqliteInline: true,
121
- }),
122
- ],
123
- },
124
- );
125
-
126
- export const apiKeysV100 = table(
127
- "api_keys",
128
- {
129
- id: idColumn("id", varchar(255)),
130
- hash: stringColumn("hash"),
131
- name: stringColumn("name"),
132
- prefix: stringColumn("prefix"),
133
- role: stringColumn("role"),
134
- created_at_ms: float("created_at_ms"),
135
- revoked_at_ms: float("revoked_at_ms").nullable(),
136
- },
137
- {
138
- indexes: [
139
- uniqueIndex("api_keys_hash_key", ["hash"]),
140
- index("api_keys_created_at_idx", ["created_at_ms", "id"]),
141
- ],
142
- checks: [
143
- check({
144
- name: "api_keys_role_check",
145
- expression: "role = 'client'",
146
- sqliteInline: true,
147
- }),
148
- check({
149
- name: "api_keys_created_at_check",
150
- expression: "created_at_ms >= 0",
151
- sqliteInline: true,
152
- }),
153
- check({
154
- name: "api_keys_revoked_at_check",
155
- expression: "revoked_at_ms is null or revoked_at_ms >= 0",
156
- sqliteInline: true,
157
- }),
158
- ],
159
- },
160
- );
161
-
162
- export const bundlesV100 = table(
163
- "bundles",
164
- {
165
- id: idColumn("id", "uuid"),
166
- platform: stringColumn("platform"),
167
- file_hash: stringColumn("file_hash"),
168
- git_commit_hash: stringColumn("git_commit_hash").nullable(),
169
- storage_uri: stringColumn("storage_uri"),
170
- archive_byte_size: float("archive_byte_size"),
171
- metadata: json("metadata").defaultTo({}),
172
- manifest_storage_uri: stringColumn("manifest_storage_uri").nullable(),
173
- manifest_file_hash: stringColumn("manifest_file_hash").nullable(),
174
- asset_base_storage_uri: stringColumn("asset_base_storage_uri").nullable(),
175
- },
176
- {
177
- indexes: [index("bundles_platform_idx", ["platform"], ["mongodb"])],
178
- checks: [
179
- check({
180
- name: "bundles_archive_byte_size_check",
181
- expression:
182
- "archive_byte_size >= 0 and archive_byte_size <= 9007199254740991",
183
- sqliteInline: true,
184
- }),
185
- ],
186
- },
187
- );
188
-
189
- export const releasesV100 = table(
190
- "releases",
191
- {
192
- id: idColumn("id", "uuid"),
193
- revision: integer("revision"),
194
- scope_key: column("scope_key", varchar(2048)).collate(catalogKeyCollations),
195
- channel_id: column("channel_id", varchar(255)).collate(
196
- channelIdentityCollations,
197
- ),
198
- platform: stringColumn("platform"),
199
- kind: stringColumn("kind"),
200
- bundle_id: column("bundle_id", "uuid").nullable(),
201
- strategy: stringColumn("strategy"),
202
- target_app_version: stringColumn("target_app_version").nullable(),
203
- fingerprint_hash: stringColumn("fingerprint_hash").nullable(),
204
- enabled: bool("enabled"),
205
- should_force_update: bool("should_force_update"),
206
- message: stringColumn("message").nullable(),
207
- rollout_cohort_count: integer("rollout_cohort_count").defaultTo(1000),
208
- target_cohorts: json("target_cohorts").defaultTo([]),
209
- operation: stringColumn("operation"),
210
- source_release_id: column("source_release_id", "uuid").nullable(),
211
- created_at_ms: float("created_at_ms"),
212
- updated_at_ms: float("updated_at_ms"),
213
- },
214
- {
215
- indexes: [
216
- index("releases_scope_order_idx", ["scope_key", "id"]),
217
- index("releases_channel_platform_order_idx", [
218
- "channel_id",
219
- "platform",
220
- "id",
221
- ]),
222
- index("releases_bundle_id_idx", ["bundle_id"]),
223
- index("releases_fingerprint_hash_idx", ["fingerprint_hash"]),
224
- index("releases_enabled_idx", ["enabled"]),
225
- ],
226
- checks: [
227
- check({
228
- name: "releases_revision_check",
229
- expression: "revision >= 1",
230
- sqliteInline: true,
231
- }),
232
- check({
233
- name: "releases_kind_bundle_check",
234
- expression:
235
- "(kind = 'BUNDLE' and bundle_id is not null) or (kind = 'EMBEDDED' and bundle_id is null)",
236
- sqliteInline: true,
237
- }),
238
- check({
239
- name: "releases_strategy_target_check",
240
- expression:
241
- "(strategy = 'APP_VERSION' and target_app_version is not null and fingerprint_hash is null) or (strategy = 'FINGERPRINT' and target_app_version is null and fingerprint_hash is not null)",
242
- sqliteInline: true,
243
- }),
244
- check({
245
- name: "releases_rollout_cohort_count_check",
246
- expression:
247
- "rollout_cohort_count >= 0 and rollout_cohort_count <= 1000",
248
- sqliteInline: true,
249
- }),
250
- check({
251
- name: "releases_operation_check",
252
- expression: "operation in ('DEPLOY', 'PROMOTE', 'ROLLBACK')",
253
- sqliteInline: true,
254
- }),
255
- ],
256
- foreignKeys: [
257
- foreignKey("releases_channel_id_fk", ["channel_id"], "channels", ["id"], {
258
- onDelete: "restrict",
259
- }),
260
- foreignKey("releases_bundle_id_fk", ["bundle_id"], "bundles", ["id"], {
261
- onDelete: "restrict",
262
- }),
263
- foreignKey(
264
- "releases_source_release_id_fk",
265
- ["source_release_id"],
266
- "releases",
267
- ["id"],
268
- { onDelete: "set null" },
269
- ),
270
- ],
271
- relations: [
272
- relation({
273
- name: "channelRecord",
274
- fieldName: "releases",
275
- targetFieldName: "channelRecord",
276
- relationName: "releases_channels",
277
- columns: ["channel_id"],
278
- referencedTable: "channels",
279
- referencedColumns: ["id"],
280
- }),
281
- relation({
282
- name: "bundle",
283
- fieldName: "releases",
284
- targetFieldName: "bundle",
285
- relationName: "releases_bundles",
286
- columns: ["bundle_id"],
287
- referencedTable: "bundles",
288
- referencedColumns: ["id"],
289
- }),
290
- relation({
291
- name: "sourceRelease",
292
- fieldName: "derivedReleases",
293
- targetFieldName: "sourceRelease",
294
- relationName: "releases_source_release",
295
- columns: ["source_release_id"],
296
- referencedTable: "releases",
297
- referencedColumns: ["id"],
298
- }),
299
- ],
300
- },
301
- );
302
-
303
- export const releaseCatalogsV100 = table(
304
- "release_catalogs",
305
- {
306
- scope_key: idColumn("scope_key", varchar(2048)).collate(
307
- catalogKeyCollations,
308
- ),
309
- catalog_id: column("catalog_id", varchar(255)),
310
- strategy: stringColumn("strategy"),
311
- channel_id: column("channel_id", varchar(255)).collate(
312
- channelIdentityCollations,
313
- ),
314
- channel_key: column("channel_key", varchar(1400)).collate(
315
- catalogKeyCollations,
316
- ),
317
- platform: stringColumn("platform"),
318
- fingerprint_hash: stringColumn("fingerprint_hash").nullable(),
319
- generation: float("generation"),
320
- payload: largeString("payload"),
321
- catalog_hash: column("catalog_hash", varchar(71)),
322
- byte_size: integer("byte_size"),
323
- is_tombstone: bool("is_tombstone"),
324
- updated_at_ms: float("updated_at_ms"),
325
- },
326
- {
327
- indexes: [index("release_catalogs_channel_idx", ["channel_id"])],
328
- checks: [
329
- check({
330
- name: "release_catalogs_strategy_target_check",
331
- expression:
332
- "(strategy = 'APP_VERSION' and fingerprint_hash is null) or (strategy = 'FINGERPRINT' and fingerprint_hash is not null)",
333
- sqliteInline: true,
334
- }),
335
- check({
336
- name: "release_catalogs_generation_check",
337
- expression: "generation >= 1 and generation <= 9007199254740991",
338
- sqliteInline: true,
339
- }),
340
- check({
341
- name: "release_catalogs_byte_size_check",
342
- expression: "byte_size >= 0 and byte_size <= 262144",
343
- sqliteInline: true,
344
- }),
345
- ],
346
- foreignKeys: [
347
- foreignKey(
348
- "release_catalogs_channel_id_fk",
349
- ["channel_id"],
350
- "channels",
351
- ["id"],
352
- { onDelete: "restrict" },
353
- ),
354
- ],
355
- relations: [
356
- relation({
357
- name: "channelRecord",
358
- fieldName: "releaseCatalogs",
359
- targetFieldName: "channelRecord",
360
- relationName: "release_catalogs_channels",
361
- columns: ["channel_id"],
362
- referencedTable: "channels",
363
- referencedColumns: ["id"],
364
- }),
365
- ],
366
- },
367
- );
368
-
369
- const insightsTextCollations = {
370
- postgresql: '"C"',
371
- mysql: "utf8mb4_0900_bin",
372
- } as const;
373
- const insightsProviders = [
374
- "postgresql",
375
- "mysql",
376
- "sqlite",
377
- "cockroachdb",
378
- "mongodb",
379
- ] as const;
380
-
381
- export const bundleEventsV100 = table(
382
- "bundle_events",
383
- {
384
- id: idColumn("id", "uuid"),
385
- type: column("type", varchar(32)),
386
- install_id: column("install_id", varchar(255)).collate(
387
- insightsTextCollations,
388
- ),
389
- user_id: column("user_id", varchar(255))
390
- .collate(insightsTextCollations)
391
- .nullable(),
392
- username: stringColumn("username").nullable(),
393
- from_release_id: uuid("from_release_id").nullable(),
394
- from_bundle_id: uuid("from_bundle_id").nullable(),
395
- to_release_id: uuid("to_release_id").nullable(),
396
- to_bundle_id: uuid("to_bundle_id"),
397
- platform: stringColumn("platform").collate(insightsTextCollations),
398
- app_version: stringColumn("app_version"),
399
- channel: stringColumn("channel").collate(insightsTextCollations),
400
- cohort: stringColumn("cohort"),
401
- update_strategy: stringColumn("update_strategy").nullable(),
402
- fingerprint_hash: stringColumn("fingerprint_hash").nullable(),
403
- sdk_version: stringColumn("sdk_version").nullable(),
404
- received_at_ms: float("received_at_ms"),
405
- },
406
- {
407
- indexes: [
408
- index("bundle_events_received_at_idx", ["received_at_ms", "id"]),
409
- index("bundle_events_install_idx", [
410
- "install_id",
411
- "type",
412
- "received_at_ms",
413
- "id",
414
- ]),
415
- index(
416
- "bundle_events_from_bundle_idx",
417
- [
418
- "type",
419
- "platform",
420
- "channel",
421
- "from_bundle_id",
422
- "received_at_ms",
423
- "id",
424
- ],
425
- insightsProviders,
426
- ),
427
- index(
428
- "bundle_events_to_bundle_idx",
429
- ["type", "platform", "channel", "to_bundle_id", "received_at_ms", "id"],
430
- insightsProviders,
431
- ),
432
- ],
433
- checks: [
434
- check({
435
- name: "bundle_events_type_check",
436
- expression:
437
- "type in ('UPDATE_APPLIED', 'RECOVERED', 'RELEASE_ADOPTED', 'UNCHANGED')",
438
- sqliteInline: true,
439
- }),
440
- check({
441
- name: "bundle_events_platform_check",
442
- expression: "platform in ('ios', 'android')",
443
- sqliteInline: true,
444
- }),
445
- check({
446
- name: "bundle_events_shape_check",
447
- expression:
448
- "((type in ('UPDATE_APPLIED', 'RECOVERED', 'RELEASE_ADOPTED')) and from_bundle_id is not null and update_strategy is not null and update_strategy in ('fingerprint', 'appVersion')) or (type = 'UNCHANGED' and from_bundle_id is null and update_strategy is null)",
449
- sqliteInline: true,
450
- }),
451
- check({
452
- name: "bundle_events_received_at_check",
453
- expression: "received_at_ms >= 0",
454
- sqliteInline: true,
455
- }),
456
- ],
457
- },
458
- );
459
-
460
- export const bundleInstallationsV100 = table(
461
- "bundle_installations",
462
- {
463
- install_id: idColumn("install_id", varchar(255)).collate(
464
- insightsTextCollations,
465
- ),
466
- id: uuid("id"),
467
- user_id: column("user_id", varchar(255))
468
- .collate(insightsTextCollations)
469
- .nullable(),
470
- username: stringColumn("username").nullable(),
471
- to_bundle_id: uuid("to_bundle_id"),
472
- type: column("type", varchar(32)),
473
- platform: stringColumn("platform").collate(insightsTextCollations),
474
- app_version: stringColumn("app_version"),
475
- channel: stringColumn("channel").collate(insightsTextCollations),
476
- cohort: stringColumn("cohort"),
477
- received_at_ms: float("received_at_ms"),
478
- },
479
- {
480
- indexes: [
481
- index("bundle_installations_user_id_idx", ["user_id", "install_id"]),
482
- index("bundle_installations_received_at_idx", ["received_at_ms"]),
483
- index(
484
- "bundle_installations_scope_idx",
485
- ["platform", "channel", "received_at_ms"],
486
- insightsProviders,
487
- ),
488
- index(
489
- "bundle_installations_bundle_idx",
490
- ["platform", "channel", "to_bundle_id", "received_at_ms"],
491
- insightsProviders,
492
- ),
493
- ],
494
- checks: [
495
- check({
496
- name: "bundle_installations_type_check",
497
- expression:
498
- "type in ('UPDATE_APPLIED', 'RECOVERED', 'RELEASE_ADOPTED', 'UNCHANGED')",
499
- sqliteInline: true,
500
- }),
501
- check({
502
- name: "bundle_installations_platform_check",
503
- expression: "platform in ('ios', 'android')",
504
- sqliteInline: true,
505
- }),
506
- check({
507
- name: "bundle_installations_received_at_check",
508
- expression: "received_at_ms >= 0",
509
- sqliteInline: true,
510
- }),
511
- ],
512
- },
513
- );
514
-
515
- export const v1_0_0 = schema({
516
- version: "1.0.0",
517
- settingsTable: HOT_UPDATER_SETTINGS_TABLE,
518
- tables: [
519
- channelsV100,
520
- bundlesV100,
521
- bundlePatchesV100,
522
- releasesV100,
523
- releaseCatalogsV100,
524
- bundleEventsV100,
525
- bundleInstallationsV100,
526
- apiKeysV100,
527
- createSettingsTable("1.0.0"),
528
- ],
529
- });
@@ -1,152 +0,0 @@
1
- import {
2
- createStorageDownloadPath,
3
- createStoragePlugin,
4
- } from "@hot-updater/plugin-core";
5
- import { afterEach, describe, expect, it, vi } from "vitest";
6
-
7
- import { createStorageAccess } from "./storageAccess";
8
-
9
- describe("createStorageAccess", () => {
10
- afterEach(() => {
11
- vi.unstubAllGlobals();
12
- });
13
-
14
- it("reads text through a matching storage implementation", async () => {
15
- const get = vi.fn(
16
- async (_storageUri: string) => new Response("manifest text"),
17
- );
18
- const storage = createStoragePlugin({
19
- name: "r2Storage",
20
- protocol: "r2",
21
- get: async (input) => ({ response: await get(input.storageUri) }),
22
- });
23
- const { readStorageText } = createStorageAccess([storage]);
24
-
25
- await expect(readStorageText("r2://assets/manifest.json")).resolves.toBe(
26
- "manifest text",
27
- );
28
- expect(get).toHaveBeenCalledWith("r2://assets/manifest.json");
29
- });
30
-
31
- it("reads direct HTTP storage when no plugin owns the protocol", async () => {
32
- const fetchMock = vi.fn<typeof fetch>(
33
- async () => new Response("manifest text"),
34
- );
35
- vi.stubGlobal("fetch", fetchMock);
36
- const { readStorageText } = createStorageAccess([]);
37
-
38
- await expect(
39
- readStorageText("https://assets.example.com/manifest.json"),
40
- ).resolves.toBe("manifest text");
41
- });
42
-
43
- it("uses an unowned HTTPS URI directly as the download URL", async () => {
44
- const { resolveFileUrl } = createStorageAccess([]);
45
- const storageUri = "https://assets.example.com/bundle.zip";
46
-
47
- await expect(resolveFileUrl(storageUri)).resolves.toBe(storageUri);
48
- });
49
-
50
- it("lets a matching HTTPS storage own reads before direct fetch", async () => {
51
- const fetchMock = vi.fn<typeof fetch>();
52
- vi.stubGlobal("fetch", fetchMock);
53
- const get = vi.fn(
54
- async () => ({ response: new Response("owned manifest") }) as const,
55
- );
56
- const storage = createStoragePlugin({
57
- name: "standaloneStorage",
58
- protocol: "https",
59
- get,
60
- });
61
- const { readStorageText } = createStorageAccess([storage]);
62
- const storageUri = "https://storage.example.com/manifest.json";
63
-
64
- await expect(readStorageText(storageUri)).resolves.toBe("owned manifest");
65
- expect(get).toHaveBeenCalledWith({ storageUri });
66
- expect(fetchMock).not.toHaveBeenCalled();
67
- });
68
-
69
- it("lets a matching HTTPS storage resolve the download URL", async () => {
70
- const getDownloadUrl = vi.fn(async () => ({
71
- url: "https://cdn.example.com/bundle.zip",
72
- }));
73
- const storage = createStoragePlugin({
74
- name: "standaloneStorage",
75
- protocol: "https",
76
- get: async () => ({ response: null }),
77
- getDownloadUrl,
78
- });
79
- const { resolveFileUrl } = createStorageAccess([storage]);
80
- const storageUri = "https://storage.example.com/bundle.zip";
81
-
82
- await expect(resolveFileUrl(storageUri)).resolves.toBe(
83
- "https://cdn.example.com/bundle.zip",
84
- );
85
- expect(getDownloadUrl).toHaveBeenCalledWith({ storageUri });
86
- });
87
-
88
- it("creates and serves a runtime-neutral delivery URL", async () => {
89
- const storage = createStoragePlugin({
90
- name: "r2Storage",
91
- protocol: "r2",
92
- get: vi.fn(
93
- async () =>
94
- ({
95
- response: new Response("bundle", {
96
- headers: { "content-type": "application/zip" },
97
- }),
98
- }) as const,
99
- ),
100
- getDownloadUrl: async ({ storageUri }) => ({
101
- url: createStorageDownloadPath(storageUri, "test-signature"),
102
- }),
103
- });
104
- const access = createStorageAccess([storage]);
105
-
106
- const fileUrl = await access.resolveFileUrl("r2://bucket/bundle.zip");
107
- expect(fileUrl).toMatch(/^\/storage\//);
108
- const segments = fileUrl!.split("/");
109
- const token = segments.at(-2)!;
110
- const signature = segments.at(-1)!;
111
- const response = await access.downloadStorageObject!(token, signature);
112
- await expect(response?.text()).resolves.toBe("bundle");
113
- await expect(
114
- access.downloadStorageObject!(token, `${signature}tampered`),
115
- ).resolves.toBeNull();
116
- });
117
-
118
- it("lets a CDN resolver bypass built-in server delivery", async () => {
119
- const resolveUrl = vi.fn(async () => ({
120
- url: "https://cdn.example.com/bundle.zip",
121
- }));
122
- const storage = createStoragePlugin({
123
- name: "s3Storage",
124
- protocol: "s3",
125
- get: async () => ({ response: null }),
126
- getDownloadUrl: resolveUrl,
127
- });
128
- const access = createStorageAccess([storage]);
129
-
130
- await expect(access.resolveFileUrl("s3://bucket/bundle.zip")).resolves.toBe(
131
- "https://cdn.example.com/bundle.zip",
132
- );
133
- expect(access.downloadStorageObject).toEqual(expect.any(Function));
134
- });
135
-
136
- it("rejects ambiguous storage protocol ownership", () => {
137
- const first = createStoragePlugin({
138
- name: "firstR2Storage",
139
- protocol: "r2",
140
- get: async () => ({ response: null }),
141
- });
142
- const second = createStoragePlugin({
143
- name: "secondR2Storage",
144
- protocol: "r2",
145
- get: async () => ({ response: null }),
146
- });
147
-
148
- expect(() => createStorageAccess([first, second])).toThrow(
149
- "Multiple storage plugins handle protocol: r2",
150
- );
151
- });
152
- });