@hot-updater/server 0.36.6 → 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
@@ -0,0 +1,23 @@
1
+ export interface MongoMigrationBackend {
2
+ ensureCollections(): Promise<void>;
3
+ backfillData?(): Promise<void>;
4
+ validateData?(): Promise<void>;
5
+ ensureIndexes(): Promise<void>;
6
+ enforceSchema?(): Promise<void>;
7
+ updateVersion(): Promise<void>;
8
+ }
9
+
10
+ export const executeMongoMigration = async ({
11
+ backend,
12
+ updateSettings,
13
+ }: {
14
+ readonly backend: MongoMigrationBackend;
15
+ readonly updateSettings: boolean;
16
+ }): Promise<void> => {
17
+ await backend.ensureCollections();
18
+ await backend.backfillData?.();
19
+ await backend.validateData?.();
20
+ await backend.ensureIndexes();
21
+ await backend.enforceSchema?.();
22
+ if (updateSettings) await backend.updateVersion();
23
+ };
@@ -0,0 +1,25 @@
1
+ declare module "node:sqlite" {
2
+ export type SqliteValue = bigint | null | number | string | Uint8Array;
3
+
4
+ export interface StatementSync {
5
+ all: (...parameters: SqliteValue[]) => Record<string, SqliteValue>[];
6
+ columns: () => readonly unknown[];
7
+ get: (
8
+ ...parameters: SqliteValue[]
9
+ ) => Record<string, SqliteValue> | undefined;
10
+ iterate: (
11
+ ...parameters: SqliteValue[]
12
+ ) => IterableIterator<Record<string, SqliteValue>>;
13
+ run: (...parameters: SqliteValue[]) => {
14
+ readonly changes: number | bigint;
15
+ readonly lastInsertRowid: number | bigint;
16
+ };
17
+ }
18
+
19
+ export class DatabaseSync {
20
+ constructor(location: string);
21
+ close(): void;
22
+ exec(sql: string): void;
23
+ prepare(sql: string): StatementSync;
24
+ }
25
+ }
@@ -0,0 +1,148 @@
1
+ import {
2
+ createReleaseCatalogScopeKey,
3
+ NIL_UUID,
4
+ RELEASE_CATALOG_FALLBACK_POLICY,
5
+ RELEASE_CATALOG_SCHEMA_VERSION,
6
+ type ArtifactInfo,
7
+ type ReleaseCatalog,
8
+ } from "@hot-updater/core";
9
+ import {
10
+ createDatabaseClient,
11
+ projectCompiledCatalog,
12
+ projectCompiledRollbackCatalog,
13
+ type CompiledReleaseCatalog,
14
+ type DatabasePlugin,
15
+ } from "@hot-updater/plugin-core";
16
+
17
+ import { resolveManifestArtifacts } from "./updateArtifacts";
18
+
19
+ type ResolveFileUrl = (storageUri: string | null) => Promise<string | null>;
20
+ type ReadStorageText = (storageUri: string) => Promise<string | null>;
21
+
22
+ export type ReleaseCatalogRequest =
23
+ | {
24
+ readonly strategy: "APP_VERSION";
25
+ readonly platform: "ios" | "android";
26
+ readonly channelKey: string;
27
+ readonly appVersion: string;
28
+ }
29
+ | {
30
+ readonly strategy: "FINGERPRINT";
31
+ readonly platform: "ios" | "android";
32
+ readonly channelKey: string;
33
+ readonly fingerprintHash: string;
34
+ };
35
+
36
+ const parseCompiledCatalog = (
37
+ payload: string,
38
+ strategy: ReleaseCatalogRequest["strategy"],
39
+ ): CompiledReleaseCatalog => {
40
+ const parsed: unknown = JSON.parse(payload);
41
+ if (
42
+ typeof parsed !== "object" ||
43
+ parsed === null ||
44
+ Reflect.get(parsed, "schemaVersion") !== RELEASE_CATALOG_SCHEMA_VERSION ||
45
+ Reflect.get(parsed, "strategy") !== strategy ||
46
+ Reflect.get(parsed, "fallbackPolicy") !== RELEASE_CATALOG_FALLBACK_POLICY ||
47
+ !Array.isArray(Reflect.get(parsed, "releaseDescriptors"))
48
+ ) {
49
+ throw new Error("Stored Release catalog payload is invalid");
50
+ }
51
+ if (
52
+ strategy === "APP_VERSION" &&
53
+ !Array.isArray(Reflect.get(parsed, "segments"))
54
+ ) {
55
+ throw new Error("Stored app-version Release catalog is invalid");
56
+ }
57
+ if (
58
+ strategy === "FINGERPRINT" &&
59
+ !Array.isArray(Reflect.get(parsed, "releaseIndexes"))
60
+ ) {
61
+ throw new Error("Stored fingerprint Release catalog is invalid");
62
+ }
63
+ return parsed as CompiledReleaseCatalog;
64
+ };
65
+
66
+ export const createReleaseCatalogReader =
67
+ (database: DatabasePlugin) =>
68
+ async (input: ReleaseCatalogRequest): Promise<ReleaseCatalog | null> => {
69
+ const scopeKey =
70
+ input.strategy === "APP_VERSION"
71
+ ? createReleaseCatalogScopeKey({
72
+ channelKey: input.channelKey,
73
+ platform: input.platform,
74
+ strategy: "APP_VERSION",
75
+ })
76
+ : createReleaseCatalogScopeKey({
77
+ channelKey: input.channelKey,
78
+ fingerprintHash: input.fingerprintHash,
79
+ platform: input.platform,
80
+ strategy: "FINGERPRINT",
81
+ });
82
+ const row = await database.models.releaseCatalogs.findByScopeKey(scopeKey);
83
+ if (
84
+ row === null ||
85
+ row.platform !== input.platform ||
86
+ row.strategy !== input.strategy ||
87
+ row.channel_key !== input.channelKey ||
88
+ row.scope_key !== scopeKey ||
89
+ row.fingerprint_hash !==
90
+ (input.strategy === "FINGERPRINT" ? input.fingerprintHash : null)
91
+ ) {
92
+ return null;
93
+ }
94
+ const compiled = parseCompiledCatalog(row.payload, input.strategy);
95
+ const releases = projectCompiledCatalog(
96
+ compiled,
97
+ input.strategy === "APP_VERSION" ? input.appVersion : undefined,
98
+ );
99
+ const rollbackReleases = projectCompiledRollbackCatalog(
100
+ compiled,
101
+ input.strategy === "APP_VERSION" ? input.appVersion : undefined,
102
+ );
103
+ return {
104
+ catalogId: row.catalog_id,
105
+ catalogHash: row.catalog_hash,
106
+ fallbackPolicy: RELEASE_CATALOG_FALLBACK_POLICY,
107
+ generation: row.generation,
108
+ releases,
109
+ rollbackReleases,
110
+ schemaVersion: RELEASE_CATALOG_SCHEMA_VERSION,
111
+ scopeKey,
112
+ };
113
+ };
114
+
115
+ export const createArtifactResolver = (input: {
116
+ readonly database: DatabasePlugin;
117
+ readonly readStorageText?: ReadStorageText;
118
+ readonly resolveFileUrl: ResolveFileUrl;
119
+ }) => {
120
+ const databaseClient = createDatabaseClient(input.database);
121
+
122
+ return async (
123
+ targetBundleId: string,
124
+ currentBundleId: string,
125
+ ): Promise<ArtifactInfo | null> => {
126
+ const [targetBundle, currentBundle] = await Promise.all([
127
+ databaseClient.getBundleById(targetBundleId),
128
+ currentBundleId === NIL_UUID
129
+ ? null
130
+ : databaseClient.getBundleById(currentBundleId),
131
+ ]);
132
+ if (targetBundle === null) return null;
133
+ const fileUrl = await input.resolveFileUrl(targetBundle.storageUri);
134
+ const base: ArtifactInfo = {
135
+ fileHash: targetBundle.fileHash,
136
+ fileUrl,
137
+ };
138
+ if (input.readStorageText === undefined) return base;
139
+ const manifest = await resolveManifestArtifacts({
140
+ archiveUrlUsable: fileUrl !== null,
141
+ currentBundle,
142
+ readStorageText: input.readStorageText,
143
+ resolveFileUrl: input.resolveFileUrl,
144
+ targetBundle,
145
+ });
146
+ return manifest === null ? base : { ...base, ...manifest };
147
+ };
148
+ };
@@ -6,21 +6,35 @@ export const createMongoMigrationOperations = (
6
6
  settingsOperation?: MigrationOperation,
7
7
  ): MigrationOperation[] => [
8
8
  ...hotUpdaterCreateTableOperations,
9
- {
10
- type: "custom",
11
- sql: "create index bundles_id_idx on bundles(id)",
12
- },
9
+ ...hotUpdaterSchema.tables
10
+ .filter((table) => !table.internal)
11
+ .map((table): MigrationOperation => {
12
+ const primaryKey = table.columns.find((column) => column.primaryKey);
13
+ if (!primaryKey) {
14
+ throw new Error(
15
+ `MongoDB table ${table.ormName} does not define a primary key.`,
16
+ );
17
+ }
18
+ return {
19
+ description: `Create unique MongoDB index: ${table.ormName}_${primaryKey.ormName}_idx on ${table.ormName}(${primaryKey.ormName})`,
20
+ type: "custom",
21
+ };
22
+ }),
13
23
  ...hotUpdaterSchema.tables.flatMap((table) =>
14
24
  (table.indexes ?? [])
15
25
  .filter((index) => schemaIndexAppliesToProvider(index, "mongodb"))
16
26
  .map(
17
27
  (index): MigrationOperation => ({
18
- type: "custom",
19
- sql: `create index ${index.name} on ${table.ormName}(${index.columns.join(
28
+ description: `Create ${index.unique ? "unique " : ""}MongoDB index: ${index.name} on ${table.ormName}(${index.columns.join(
20
29
  ", ",
21
30
  )})`,
31
+ type: "custom",
22
32
  }),
23
33
  ),
24
34
  ),
35
+ {
36
+ description: "Enforce final MongoDB Bundle, Release, and catalog schemas",
37
+ type: "custom",
38
+ },
25
39
  ...(settingsOperation ? [settingsOperation] : []),
26
40
  ];
@@ -38,19 +38,31 @@ export const getSqlType = (
38
38
  ): string => {
39
39
  if (provider === "sqlite") {
40
40
  if (type === "bool" || type === "integer") return "integer";
41
+ if (type === "float") return "real";
41
42
  return "text";
42
43
  }
43
44
  if (provider === "mysql") {
44
45
  if (type === "uuid") return "char(36)";
45
46
  if (type === "bool") return "boolean";
46
47
  if (type === "integer") return "integer";
48
+ if (type === "float") return "double";
47
49
  if (type === "json") return "json";
50
+ if (type === "large-string") return "mediumtext";
48
51
  if (type.startsWith("varchar")) return type;
49
52
  return "text";
50
53
  }
54
+ if (provider === "mssql") {
55
+ if (type === "uuid") return "uniqueidentifier";
56
+ if (type === "bool") return "bit";
57
+ if (type === "integer") return "int";
58
+ if (type === "float") return "float";
59
+ if (type.startsWith("varchar")) return type.replace("varchar", "nvarchar");
60
+ return "nvarchar(max)";
61
+ }
51
62
  if (type === "uuid") return "uuid";
52
63
  if (type === "bool") return "boolean";
53
64
  if (type === "integer") return "integer";
65
+ if (type === "float") return "double precision";
54
66
  if (type === "json") return "json";
55
67
  if (type.startsWith("varchar")) return type;
56
68
  return "text";
@@ -67,7 +79,9 @@ const sqlDefaultClause = (
67
79
  if (!value) return "";
68
80
  if (
69
81
  provider === "mysql" &&
70
- (column.type === "json" || column.type === "string")
82
+ (column.type === "json" ||
83
+ column.type === "large-string" ||
84
+ column.type === "string")
71
85
  ) {
72
86
  return "";
73
87
  }
@@ -103,12 +117,21 @@ export const sqlColumnDefinition = (
103
117
  column.primaryKey ? "primary key" : undefined,
104
118
  column.nullable ? undefined : "not null",
105
119
  ].filter(Boolean);
120
+ const collation = column.providerCollations?.[provider];
121
+ const collationClause = collation
122
+ ? provider === "mysql"
123
+ ? `character set ${collation === "ascii_bin" ? "ascii" : "utf8mb4"} collate ${collation}`
124
+ : `collate ${collation}`
125
+ : undefined;
106
126
  return (
107
127
  [
108
128
  sqlColumnName(table, column, provider),
109
129
  getSqlType(column.type, provider),
130
+ collationClause,
110
131
  ...constraints,
111
- ].join(" ") + sqlDefaultClause(column, provider)
132
+ ]
133
+ .filter(Boolean)
134
+ .join(" ") + sqlDefaultClause(column, provider)
112
135
  );
113
136
  };
114
137
 
@@ -125,24 +148,30 @@ const sqlIndexColumn = (
125
148
 
126
149
  export const createIndexSql = (
127
150
  table: HotUpdaterTableSchema,
128
- index: { readonly name: string; readonly columns: readonly string[] },
151
+ index: {
152
+ readonly name: string;
153
+ readonly columns: readonly string[];
154
+ readonly unique?: true;
155
+ },
129
156
  provider: ORMSQLProvider,
130
157
  ): string =>
131
- `create index ${index.name} on ${table.ormName}(${index.columns
158
+ `create ${index.unique ? "unique " : ""}index ${index.name} on ${table.ormName}(${index.columns
132
159
  .map((column) => sqlIndexColumn(table, column, provider))
133
160
  .join(", ")})`;
134
161
 
135
162
  export const createForeignKeySql = (
136
163
  table: HotUpdaterTableSchema,
137
164
  foreignKey: HotUpdaterForeignKeySchema,
165
+ provider?: ORMSQLProvider,
138
166
  ): string =>
139
- `alter table ${table.ormName} add constraint ${foreignKey.name} foreign key (${foreignKey.columns.join(", ")}) references ${foreignKey.referencedTable}(${foreignKey.referencedColumns.join(", ")}) on update ${foreignKey.onUpdate} on delete ${foreignKey.onDelete}`;
167
+ `alter table ${table.ormName} add constraint ${foreignKey.name} foreign key (${foreignKey.columns.join(", ")}) references ${foreignKey.referencedTable}(${foreignKey.referencedColumns.join(", ")}) on update ${provider === "mssql" && foreignKey.onUpdate === "restrict" ? "no action" : foreignKey.onUpdate} on delete ${provider === "mssql" && foreignKey.onDelete === "restrict" ? "no action" : foreignKey.onDelete}`;
140
168
 
141
169
  export const createCheckSql = (
142
170
  table: HotUpdaterTableSchema,
143
171
  check: HotUpdaterCheckSchema,
172
+ provider?: ORMSQLProvider,
144
173
  ): string =>
145
- `alter table ${table.ormName} add constraint ${check.name} check (${check.expression})`;
174
+ `alter table ${table.ormName} add constraint ${check.name} check (${(provider && check.providerExpressions?.[provider]) ?? check.expression})`;
146
175
 
147
176
  const inlineSqlChecks = (
148
177
  table: HotUpdaterTableSchema,
@@ -151,20 +180,30 @@ const inlineSqlChecks = (
151
180
  provider === "sqlite"
152
181
  ? (table.checks ?? [])
153
182
  .filter((check) => check.sqliteInline)
154
- .map((check) => `constraint ${check.name} check (${check.expression})`)
183
+ .map(
184
+ (check) =>
185
+ `constraint ${check.name} check (${check.providerExpressions?.sqlite ?? check.expression})`,
186
+ )
155
187
  : [];
156
188
 
157
189
  export const createTableStatement = (
158
190
  table: HotUpdaterTableSchema,
159
191
  provider: ORMSQLProvider,
192
+ relationMode: RelationMode = "foreign-keys",
160
193
  ): string => {
161
194
  const lines = [
162
195
  ...table.columns.map((column) =>
163
196
  sqlColumnDefinition(table, column, provider),
164
197
  ),
165
198
  ...inlineSqlChecks(table, provider),
199
+ ...(provider === "sqlite" && relationMode === "foreign-keys"
200
+ ? (table.foreignKeys ?? []).map(
201
+ (foreignKey) =>
202
+ `constraint ${foreignKey.name} foreign key (${foreignKey.columns.join(", ")}) references ${foreignKey.referencedTable}(${foreignKey.referencedColumns.join(", ")}) on update ${foreignKey.onUpdate} on delete ${foreignKey.onDelete}`,
203
+ )
204
+ : []),
166
205
  ];
167
- return `create table if not exists ${table.ormName} (\n${lines.join(",\n")}\n)`;
206
+ return `create table ${table.ormName} (\n${lines.join(",\n")}\n)`;
168
207
  };
169
208
 
170
209
  export const createForeignKeySqlStatements = (
@@ -174,7 +213,7 @@ export const createForeignKeySqlStatements = (
174
213
  if (relationMode !== "foreign-keys" || provider === "sqlite") return [];
175
214
  return hotUpdaterSchema.tables.flatMap((table) =>
176
215
  (table.foreignKeys ?? []).map((foreignKey) =>
177
- createForeignKeySql(table, foreignKey),
216
+ createForeignKeySql(table, foreignKey, provider),
178
217
  ),
179
218
  );
180
219
  };
@@ -184,7 +223,7 @@ export const createTableSql = (
184
223
  relationMode: RelationMode = "foreign-keys",
185
224
  ): readonly string[] => [
186
225
  ...hotUpdaterSchema.tables.map((table) =>
187
- createTableStatement(table, provider),
226
+ createTableStatement(table, provider, relationMode),
188
227
  ),
189
228
  ...hotUpdaterSchema.tables.flatMap((table) =>
190
229
  (table.indexes ?? [])
@@ -194,7 +233,9 @@ export const createTableSql = (
194
233
  ...(provider === "sqlite"
195
234
  ? []
196
235
  : hotUpdaterSchema.tables.flatMap((table) =>
197
- (table.checks ?? []).map((check) => createCheckSql(table, check)),
236
+ (table.checks ?? []).map((check) =>
237
+ createCheckSql(table, check, provider),
238
+ ),
198
239
  )),
199
240
  ...createForeignKeySqlStatements(provider, relationMode),
200
241
  ];
@@ -1,4 +1,5 @@
1
1
  import {
2
+ HOT_UPDATER_CORE_SCHEMA_KEY,
2
3
  HOT_UPDATER_SCHEMA_VERSION,
3
4
  HOT_UPDATER_SETTINGS_TABLE,
4
5
  } from "../../schema/types";
@@ -17,9 +18,9 @@ import {
17
18
 
18
19
  export const getSettingsInsertSql = (provider: ORMSQLProvider) => {
19
20
  if (provider === "mysql") {
20
- return `insert into ${HOT_UPDATER_SETTINGS_TABLE} (\`key\`, value) values ('version', '${HOT_UPDATER_SCHEMA_VERSION}') on duplicate key update value = '${HOT_UPDATER_SCHEMA_VERSION}'`;
21
+ return `insert into ${HOT_UPDATER_SETTINGS_TABLE} (\`key\`, value) values ('${HOT_UPDATER_CORE_SCHEMA_KEY}', '${HOT_UPDATER_SCHEMA_VERSION}') on duplicate key update value = '${HOT_UPDATER_SCHEMA_VERSION}'`;
21
22
  }
22
- return `insert into ${HOT_UPDATER_SETTINGS_TABLE} (key, value) values ('version', '${HOT_UPDATER_SCHEMA_VERSION}') on conflict (key) do update set value = '${HOT_UPDATER_SCHEMA_VERSION}'`;
23
+ return `insert into ${HOT_UPDATER_SETTINGS_TABLE} (key, value) values ('${HOT_UPDATER_CORE_SCHEMA_KEY}', '${HOT_UPDATER_SCHEMA_VERSION}') on conflict (key) do update set value = '${HOT_UPDATER_SCHEMA_VERSION}'`;
23
24
  };
24
25
 
25
26
  export const createSqlCreateOperations = (
@@ -44,7 +45,7 @@ export const createSqlCreateOperations = (
44
45
  (table.checks ?? []).map(
45
46
  (check): MigrationOperation => ({
46
47
  type: "custom",
47
- sql: createCheckSql(table, check),
48
+ sql: createCheckSql(table, check, provider),
48
49
  }),
49
50
  ),
50
51
  )),
@@ -53,7 +54,7 @@ export const createSqlCreateOperations = (
53
54
  (table.foreignKeys ?? []).map(
54
55
  (foreignKey): MigrationOperation => ({
55
56
  type: "custom",
56
- sql: createForeignKeySql(table, foreignKey),
57
+ sql: createForeignKeySql(table, foreignKey, provider),
57
58
  }),
58
59
  ),
59
60
  )