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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. package/dist/adapters/databaseConstraintErrors.cjs +23 -0
  2. package/dist/adapters/databaseConstraintErrors.mjs +21 -0
  3. package/dist/adapters/databasePluginUtils.cjs +117 -0
  4. package/dist/adapters/databasePluginUtils.mjs +106 -0
  5. package/dist/adapters/drizzle.cjs +53 -176
  6. package/dist/adapters/drizzle.d.cts +6 -4
  7. package/dist/adapters/drizzle.d.mts +6 -4
  8. package/dist/adapters/drizzle.mjs +54 -177
  9. package/dist/adapters/drizzleCrud.cjs +250 -0
  10. package/dist/adapters/drizzleCrud.mjs +249 -0
  11. package/dist/adapters/drizzleLazyDB.cjs +84 -36
  12. package/dist/adapters/drizzleLazyDB.mjs +84 -36
  13. package/dist/adapters/drizzleQuery.cjs +68 -0
  14. package/dist/adapters/drizzleQuery.mjs +67 -0
  15. package/dist/adapters/kysely.cjs +18 -138
  16. package/dist/adapters/kysely.d.cts +3 -12
  17. package/dist/adapters/kysely.d.mts +3 -12
  18. package/dist/adapters/kysely.mjs +19 -139
  19. package/dist/adapters/kyselyCrud.cjs +254 -0
  20. package/dist/adapters/kyselyCrud.mjs +253 -0
  21. package/dist/adapters/kyselyQuery.cjs +56 -0
  22. package/dist/adapters/kyselyQuery.mjs +55 -0
  23. package/dist/adapters/mongodb.cjs +21 -174
  24. package/dist/adapters/mongodb.d.cts +3 -2
  25. package/dist/adapters/mongodb.d.mts +3 -2
  26. package/dist/adapters/mongodb.mjs +21 -174
  27. package/dist/adapters/mongodbCollections.cjs +36 -0
  28. package/dist/adapters/mongodbCollections.mjs +30 -0
  29. package/dist/adapters/mongodbQuery.cjs +77 -0
  30. package/dist/adapters/mongodbQuery.mjs +70 -0
  31. package/dist/adapters/mongodbReads.cjs +148 -0
  32. package/dist/adapters/mongodbReads.mjs +147 -0
  33. package/dist/adapters/mongodbWrites.cjs +134 -0
  34. package/dist/adapters/mongodbWrites.mjs +133 -0
  35. package/dist/adapters/prisma.cjs +205 -180
  36. package/dist/adapters/prisma.d.cts +3 -3
  37. package/dist/adapters/prisma.d.mts +3 -3
  38. package/dist/adapters/prisma.mjs +206 -181
  39. package/dist/adapters/prismaQuery.cjs +58 -0
  40. package/dist/adapters/prismaQuery.mjs +56 -0
  41. package/dist/adapters/prismaRows.cjs +198 -0
  42. package/dist/adapters/prismaRows.mjs +188 -0
  43. package/dist/analytics/bounded/activeOverview.cjs +87 -0
  44. package/dist/analytics/bounded/activeOverview.mjs +85 -0
  45. package/dist/analytics/bounded/installationSearch.cjs +42 -0
  46. package/dist/analytics/bounded/installationSearch.mjs +42 -0
  47. package/dist/analytics/bounded/persistence.cjs +39 -0
  48. package/dist/analytics/bounded/persistence.mjs +38 -0
  49. package/dist/analytics/bounded/provider.cjs +170 -0
  50. package/dist/analytics/bounded/provider.d.cts +7 -0
  51. package/dist/analytics/bounded/provider.d.mts +7 -0
  52. package/dist/analytics/bounded/provider.mjs +170 -0
  53. package/dist/analytics/bounded/scan.cjs +144 -0
  54. package/dist/analytics/bounded/scan.mjs +138 -0
  55. package/dist/analytics/domain.d.cts +121 -0
  56. package/dist/analytics/domain.d.mts +121 -0
  57. package/dist/analytics/errors.cjs +22 -0
  58. package/dist/analytics/errors.mjs +20 -0
  59. package/dist/analytics/eventInput.cjs +111 -0
  60. package/dist/analytics/eventInput.mjs +111 -0
  61. package/dist/analytics/persistence.d.cts +6 -0
  62. package/dist/analytics/persistence.d.mts +6 -0
  63. package/dist/analytics/queryInput.cjs +58 -0
  64. package/dist/analytics/queryInput.mjs +55 -0
  65. package/dist/analytics/routes.cjs +63 -0
  66. package/dist/analytics/routes.mjs +61 -0
  67. package/dist/analytics/types.d.cts +17 -0
  68. package/dist/analytics/types.d.mts +17 -0
  69. package/dist/apiKeys.cjs +139 -0
  70. package/dist/apiKeys.d.cts +50 -0
  71. package/dist/apiKeys.d.mts +50 -0
  72. package/dist/apiKeys.mjs +133 -0
  73. package/dist/createHotUpdaterCore.cjs +48 -26
  74. package/dist/createHotUpdaterCore.d.cts +49 -17
  75. package/dist/createHotUpdaterCore.d.mts +49 -17
  76. package/dist/createHotUpdaterCore.mjs +51 -29
  77. package/dist/db/createBundleDiff.cjs +45 -68
  78. package/dist/db/createBundleDiff.d.cts +3 -3
  79. package/dist/db/createBundleDiff.d.mts +3 -3
  80. package/dist/db/createBundleDiff.mjs +47 -68
  81. package/dist/db/databasePluginCore.cjs +138 -0
  82. package/dist/db/databasePluginCore.mjs +137 -0
  83. package/dist/db/fixedMigrator.cjs +36 -93
  84. package/dist/db/fixedMigrator.mjs +36 -93
  85. package/dist/db/fixedMigratorMongo.cjs +319 -0
  86. package/dist/db/fixedMigratorMongo.mjs +319 -0
  87. package/dist/db/fixedMigratorShared.cjs +23 -0
  88. package/dist/db/fixedMigratorShared.mjs +18 -0
  89. package/dist/db/mongoMigrationExecution.cjs +11 -0
  90. package/dist/db/mongoMigrationExecution.mjs +11 -0
  91. package/dist/db/releaseCatalog.cjs +66 -0
  92. package/dist/db/releaseCatalog.d.cts +17 -0
  93. package/dist/db/releaseCatalog.d.mts +17 -0
  94. package/dist/db/releaseCatalog.mjs +64 -0
  95. package/dist/db/schema/mongodb.cjs +14 -6
  96. package/dist/db/schema/mongodb.mjs +14 -6
  97. package/dist/db/schema/registry.cjs +0 -2
  98. package/dist/db/schema/registry.mjs +1 -2
  99. package/dist/db/schema/sql.cjs +31 -14
  100. package/dist/db/schema/sql.mjs +32 -13
  101. package/dist/db/schema/sqlOperations.cjs +4 -4
  102. package/dist/db/schema/sqlOperations.mjs +5 -5
  103. package/dist/db/schemaGenerators.cjs +52 -18
  104. package/dist/db/schemaGenerators.mjs +52 -18
  105. package/dist/db/schemaReadiness.cjs +4 -3
  106. package/dist/db/schemaReadiness.mjs +4 -3
  107. package/dist/db/sqlMigrationExecution.cjs +67 -0
  108. package/dist/db/sqlMigrationExecution.mjs +66 -0
  109. package/dist/db/types.cjs +2 -6
  110. package/dist/db/types.d.cts +60 -16
  111. package/dist/db/types.d.mts +60 -16
  112. package/dist/db/types.mjs +3 -6
  113. package/dist/db/updateArtifacts.cjs +114 -60
  114. package/dist/db/updateArtifacts.mjs +117 -62
  115. package/dist/handler.cjs +108 -282
  116. package/dist/handler.d.cts +3 -46
  117. package/dist/handler.d.mts +3 -46
  118. package/dist/handler.mjs +107 -281
  119. package/dist/handlerBundleRoutes.cjs +155 -0
  120. package/dist/handlerBundleRoutes.mjs +155 -0
  121. package/dist/handlerErrors.cjs +9 -0
  122. package/dist/handlerErrors.mjs +9 -0
  123. package/dist/handlerParameters.cjs +39 -0
  124. package/dist/handlerParameters.mjs +34 -0
  125. package/dist/handlerReleaseCatalogRoutes.cjs +111 -0
  126. package/dist/handlerReleaseCatalogRoutes.mjs +110 -0
  127. package/dist/handlerReleaseManagementRoutes.cjs +125 -0
  128. package/dist/handlerReleaseManagementRoutes.mjs +124 -0
  129. package/dist/handlerTypes.d.cts +63 -0
  130. package/dist/handlerTypes.d.mts +63 -0
  131. package/dist/handlerVersionRoutes.cjs +10 -0
  132. package/dist/handlerVersionRoutes.d.cts +4 -0
  133. package/dist/handlerVersionRoutes.d.mts +4 -0
  134. package/dist/handlerVersionRoutes.mjs +9 -0
  135. package/dist/index.cjs +10 -1
  136. package/dist/index.d.cts +9 -3
  137. package/dist/index.d.mts +9 -3
  138. package/dist/index.mjs +5 -2
  139. package/dist/node.cjs +19 -12
  140. package/dist/node.d.cts +15 -10
  141. package/dist/node.d.mts +15 -10
  142. package/dist/node.mjs +19 -13
  143. package/dist/package.cjs +1 -1
  144. package/dist/package.mjs +1 -1
  145. package/dist/schema/dsl.cjs +19 -2
  146. package/dist/schema/dsl.mjs +17 -3
  147. package/dist/schema/index.cjs +1 -8
  148. package/dist/schema/index.mjs +2 -8
  149. package/dist/schema/types.cjs +3 -1
  150. package/dist/schema/types.mjs +3 -2
  151. package/dist/schema/v1_0_0.cjs +364 -0
  152. package/dist/schema/v1_0_0.mjs +357 -0
  153. package/dist/storageAccess.cjs +69 -25
  154. package/dist/storageAccess.mjs +68 -25
  155. package/dist/types/index.d.cts +4 -3
  156. package/dist/types/index.d.mts +5 -4
  157. package/package.json +8 -7
  158. package/src/adapters/databaseConstraintErrors.ts +25 -0
  159. package/src/adapters/databasePluginTestDatabase.ts +106 -0
  160. package/src/adapters/databasePluginUtils.spec.ts +29 -0
  161. package/src/adapters/databasePluginUtils.ts +214 -0
  162. package/src/adapters/drizzle.spec.ts +208 -47
  163. package/src/adapters/drizzle.ts +106 -293
  164. package/src/adapters/drizzleCrud.ts +419 -0
  165. package/src/adapters/drizzleLazyDB.ts +206 -100
  166. package/src/adapters/drizzleQuery.ts +164 -0
  167. package/src/adapters/kysely.spec.ts +126 -88
  168. package/src/adapters/kysely.ts +76 -334
  169. package/src/adapters/kyselyCrud.ts +588 -0
  170. package/src/adapters/kyselyQuery.ts +128 -0
  171. package/src/adapters/mongodb.spec.ts +141 -0
  172. package/src/adapters/mongodb.ts +60 -288
  173. package/src/adapters/mongodbCollections.ts +62 -0
  174. package/src/adapters/mongodbQuery.ts +226 -0
  175. package/src/adapters/mongodbReads.ts +311 -0
  176. package/src/adapters/mongodbRows.spec.ts +64 -0
  177. package/src/adapters/mongodbRows.ts +118 -0
  178. package/src/adapters/mongodbTestClient.ts +342 -0
  179. package/src/adapters/mongodbTestFilter.ts +166 -0
  180. package/src/adapters/mongodbWrites.ts +260 -0
  181. package/src/adapters/prisma.spec.ts +196 -0
  182. package/src/adapters/prisma.ts +417 -292
  183. package/src/adapters/prismaQuery.ts +129 -0
  184. package/src/adapters/prismaRows.spec.ts +98 -0
  185. package/src/adapters/prismaRows.ts +301 -0
  186. package/src/adapters/prismaTestClient.ts +396 -0
  187. package/src/analytics/analytics.integration.spec.ts +144 -0
  188. package/src/analytics/bounded/activeOverview.spec.ts +189 -0
  189. package/src/analytics/bounded/activeOverview.ts +148 -0
  190. package/src/analytics/bounded/installationSearch.spec.ts +130 -0
  191. package/src/analytics/bounded/installationSearch.ts +69 -0
  192. package/src/analytics/bounded/persistence.ts +43 -0
  193. package/src/analytics/bounded/provider.spec.ts +219 -0
  194. package/src/analytics/bounded/provider.ts +229 -0
  195. package/src/analytics/bounded/scan.ts +235 -0
  196. package/src/analytics/domain.ts +139 -0
  197. package/src/analytics/errors.ts +18 -0
  198. package/src/analytics/eventInput.ts +168 -0
  199. package/src/analytics/persistence.ts +10 -0
  200. package/src/analytics/queryInput.ts +102 -0
  201. package/src/analytics/routes.ts +123 -0
  202. package/src/analytics/types.ts +44 -0
  203. package/src/apiKeys.integration.spec.ts +192 -0
  204. package/src/apiKeys.spec.ts +162 -0
  205. package/src/apiKeys.ts +220 -0
  206. package/src/createHotUpdaterCore.ts +164 -100
  207. package/src/db/bundleRows.spec.ts +164 -0
  208. package/src/db/bundleRows.ts +10 -140
  209. package/src/db/createBundleDiff.spec.ts +172 -127
  210. package/src/db/createBundleDiff.ts +91 -110
  211. package/src/db/databasePluginCore.spec.ts +62 -0
  212. package/src/db/databasePluginCore.testFixtures.ts +76 -0
  213. package/src/db/databasePluginCore.ts +185 -0
  214. package/src/db/databasePluginUpdateCheck.bench.ts +107 -0
  215. package/src/db/fixedMigrator.spec.ts +184 -42
  216. package/src/db/fixedMigrator.ts +64 -205
  217. package/src/db/fixedMigratorMongo.spec.ts +192 -0
  218. package/src/db/fixedMigratorMongo.ts +425 -0
  219. package/src/db/fixedMigratorShared.ts +36 -0
  220. package/src/db/hotUpdaterSchema.ts +0 -1
  221. package/src/db/index.spec.ts +333 -1025
  222. package/src/db/mongoMigrationExecution.ts +23 -0
  223. package/src/db/node-sqlite.d.ts +25 -0
  224. package/src/db/releaseCatalog.ts +148 -0
  225. package/src/db/schema/mongodb.ts +20 -6
  226. package/src/db/schema/sql.ts +52 -11
  227. package/src/db/schema/sqlOperations.ts +5 -4
  228. package/src/db/schemaGenerators.ts +107 -23
  229. package/src/db/schemaReadiness.ts +2 -1
  230. package/src/db/sqlMigrationExecution.spec.ts +65 -0
  231. package/src/db/sqlMigrationExecution.ts +108 -0
  232. package/src/db/types.spec.ts +55 -0
  233. package/src/db/types.ts +129 -65
  234. package/src/db/updateArtifacts.spec.ts +359 -0
  235. package/src/db/updateArtifacts.ts +290 -126
  236. package/src/handler-standalone.integration.spec.ts +401 -364
  237. package/src/handler.spec.ts +137 -582
  238. package/src/handler.testFixtures.ts +30 -0
  239. package/src/handler.ts +218 -616
  240. package/src/handlerAuth.integration.spec.ts +33 -0
  241. package/src/handlerBundleRoutes.ts +259 -0
  242. package/src/handlerErrors.ts +7 -0
  243. package/src/handlerManagement.spec.ts +262 -0
  244. package/src/handlerParameters.ts +105 -0
  245. package/src/handlerReleaseCatalogRoutes.ts +154 -0
  246. package/src/handlerReleaseManagementRoutes.ts +213 -0
  247. package/src/handlerTypes.ts +96 -0
  248. package/src/handlerVersionRoutes.ts +12 -0
  249. package/src/index.ts +22 -2
  250. package/src/node.spec.ts +79 -10
  251. package/src/node.ts +20 -17
  252. package/src/releaseCatalogRoutes.integration.spec.ts +238 -0
  253. package/src/runtime.spec.ts +126 -959
  254. package/src/runtime.testFixtures.ts +71 -0
  255. package/src/schema/dsl-all-versions.spec.ts +26 -17
  256. package/src/schema/dsl.ts +41 -2
  257. package/src/schema/index.ts +3 -9
  258. package/src/schema/types.ts +9 -3
  259. package/src/schema/v1_0_0.spec.ts +146 -0
  260. package/src/schema/v1_0_0.ts +465 -0
  261. package/src/storageAccess.spec.ts +127 -32
  262. package/src/storageAccess.ts +106 -55
  263. package/src/types/index.ts +2 -1
  264. package/dist/db/bundleRows.cjs +0 -82
  265. package/dist/db/bundleRows.d.cts +0 -33
  266. package/dist/db/bundleRows.d.mts +0 -33
  267. package/dist/db/bundleRows.mjs +0 -79
  268. package/dist/db/pluginCore.cjs +0 -242
  269. package/dist/db/pluginCore.mjs +0 -241
  270. package/dist/db/schema/sqlMigrations.cjs +0 -74
  271. package/dist/db/schema/sqlMigrations.mjs +0 -73
  272. package/dist/db/schemaEnhancements.cjs +0 -20
  273. package/dist/db/schemaEnhancements.mjs +0 -19
  274. package/dist/route.cjs +0 -7
  275. package/dist/route.mjs +0 -7
  276. package/dist/schema/v0_21_0.cjs +0 -38
  277. package/dist/schema/v0_21_0.mjs +0 -37
  278. package/dist/schema/v0_29_0.cjs +0 -45
  279. package/dist/schema/v0_29_0.mjs +0 -44
  280. package/dist/schema/v0_31_0.cjs +0 -82
  281. package/dist/schema/v0_31_0.mjs +0 -80
  282. package/src/db/pluginCore.spec.ts +0 -1095
  283. package/src/db/pluginCore.ts +0 -475
  284. package/src/db/pluginUpdateCheck.bench.ts +0 -254
  285. package/src/db/schema/sqlMigrations.ts +0 -219
  286. package/src/db/schemaEnhancements.ts +0 -55
  287. package/src/route.ts +0 -7
  288. package/src/schema/v0_21_0.ts +0 -52
  289. package/src/schema/v0_29_0.ts +0 -62
  290. package/src/schema/v0_31_0.spec.ts +0 -73
  291. package/src/schema/v0_31_0.ts +0 -120
@@ -1,201 +1,226 @@
1
1
  import { getHotUpdaterSchemaVersion, hotUpdaterSchema } from "../db/schema/registry.mjs";
2
2
  import { generatePrismaSchema } from "../db/schemaGenerators.mjs";
3
- import { bundleToPatchRows, bundleToRow, rowToBundle } from "../db/bundleRows.mjs";
4
- import { calculatePagination, createDatabasePlugin, filterCompatibleAppVersions, resolveUpdateInfoFromBundles } from "@hot-updater/plugin-core";
5
- import { NIL_UUID } from "@hot-updater/core";
3
+ import { isChannelDeleteReferencedError, translateChannelDeleteError } from "./databaseConstraintErrors.mjs";
4
+ import { hasNullOrderOverrides, sortRowsByOrder } from "./databasePluginUtils.mjs";
5
+ import { createPrismaOrderBy, createPrismaWhere } from "./prismaQuery.mjs";
6
+ import { PrismaAdapterError, getPrismaDelegate, parsePrismaApiKeyRow, parsePrismaBundleEventRow, parsePrismaBundleRow, parsePrismaChannelRow, parsePrismaPatchRow, parsePrismaReleaseCatalogRow, parsePrismaReleaseRow, parsePrismaRows } from "./prismaRows.mjs";
7
+ import { DatabasePluginInputError, createDatabasePlugin } from "@hot-updater/plugin-core";
8
+ import { createDatabasePluginAdapter } from "@hot-updater/plugin-core/internal";
6
9
  //#region src/adapters/prisma.ts
7
- const assertSupportedRelationMode = (relationMode) => {
8
- if (relationMode && relationMode !== "prisma" && relationMode !== "foreign-keys") throw new Error(`Unsupported Prisma relation mode: ${relationMode}`);
10
+ const hasCallbackTransaction = (client) => "$transaction" in client && typeof client.$transaction === "function";
11
+ const runPrismaTransaction = (client, isolationLevel, callback) => {
12
+ const execute = () => isolationLevel === "serializable" ? client.$transaction(callback, { isolationLevel: "Serializable" }) : client.$transaction(callback);
13
+ if (isolationLevel === "default") return execute();
14
+ return (async () => {
15
+ for (let attempt = 0;; attempt += 1) try {
16
+ return await execute();
17
+ } catch (error) {
18
+ if (attempt >= 2 || typeof error !== "object" || error === null || !("code" in error) || error.code !== "P2034") throw error;
19
+ }
20
+ })();
9
21
  };
10
- const getDelegate = (prisma, model) => {
11
- const delegate = prisma[model];
12
- if (!delegate || typeof delegate !== "object") throw new Error(`Prisma client is missing model delegate "${model}".`);
13
- return delegate;
22
+ const assertPrismaProvider = (provider) => {
23
+ if (provider === "mongodb") throw new PrismaAdapterError("Prisma adapter does not support MongoDB; use mongodbAdapter instead");
14
24
  };
15
- const prismaWhere = (where) => {
16
- const targetAppVersionFilters = [];
17
- if (where?.targetAppVersion !== void 0) targetAppVersionFilters.push({ target_app_version: where.targetAppVersion });
18
- if (where?.targetAppVersionIn) targetAppVersionFilters.push({ target_app_version: { in: where.targetAppVersionIn } });
19
- if (where?.targetAppVersionNotNull) targetAppVersionFilters.push({ target_app_version: { not: null } });
20
- return {
21
- ...where?.channel !== void 0 ? { channel: where.channel } : {},
22
- ...where?.platform !== void 0 ? { platform: where.platform } : {},
23
- ...where?.enabled !== void 0 ? { enabled: where.enabled } : {},
24
- ...where?.fingerprintHash !== void 0 ? { fingerprint_hash: where.fingerprintHash } : {},
25
- ...where?.id ? { id: {
26
- ...where.id.eq !== void 0 ? { equals: where.id.eq } : {},
27
- ...where.id.gt !== void 0 ? { gt: where.id.gt } : {},
28
- ...where.id.gte !== void 0 ? { gte: where.id.gte } : {},
29
- ...where.id.lt !== void 0 ? { lt: where.id.lt } : {},
30
- ...where.id.lte !== void 0 ? { lte: where.id.lte } : {},
31
- ...where.id.in !== void 0 ? { in: where.id.in } : {}
32
- } } : {},
33
- ...targetAppVersionFilters.length > 0 ? { AND: targetAppVersionFilters } : {}
34
- };
25
+ const findMany = async (client, input, provider) => {
26
+ if (input.distinctOn !== void 0) throw new DatabasePluginInputError("invalid-operation");
27
+ const rawOrderBy = input.orderBy;
28
+ const orderBy = createPrismaOrderBy(rawOrderBy);
29
+ const rows = rawOrderBy !== void 0 && hasNullOrderOverrides(rawOrderBy) ? sortRowsByOrder(await getPrismaDelegate(client, input.model).findMany({ where: createPrismaWhere(input.where, provider) }), rawOrderBy).slice(input.offset, input.offset + input.limit) : await getPrismaDelegate(client, input.model).findMany({
30
+ where: createPrismaWhere(input.where, provider),
31
+ ...orderBy ? { orderBy } : {},
32
+ skip: input.offset,
33
+ take: input.limit
34
+ });
35
+ switch (input.model) {
36
+ case "bundles": return parsePrismaRows(rows, parsePrismaBundleRow);
37
+ case "bundle_patches": return parsePrismaRows(rows, parsePrismaPatchRow);
38
+ case "bundle_events": return parsePrismaRows(rows, parsePrismaBundleEventRow);
39
+ case "channels": return parsePrismaRows(rows, parsePrismaChannelRow);
40
+ case "api_keys": return parsePrismaRows(rows, parsePrismaApiKeyRow);
41
+ case "releases": return parsePrismaRows(rows, parsePrismaReleaseRow);
42
+ case "release_catalogs": return parsePrismaRows(rows, parsePrismaReleaseCatalogRow);
43
+ }
35
44
  };
36
- const createPrismaPlugin = createDatabasePlugin({
37
- name: "prisma",
38
- factory: (config) => {
39
- const prisma = config.prisma;
40
- const runInTransaction = async (operation) => {
41
- if (typeof prisma.$transaction !== "function") return operation(prisma);
42
- return prisma.$transaction(operation);
43
- };
44
- const fetchPatchMap = async (bundleIds) => {
45
- const patches = getDelegate(prisma, "bundle_patches");
46
- const patchMap = /* @__PURE__ */ new Map();
47
- if (bundleIds.length === 0) return patchMap;
48
- const rows = await patches.findMany({
49
- where: { bundle_id: { in: [...bundleIds] } },
50
- orderBy: { order_index: "asc" }
51
- });
52
- for (const row of rows) {
53
- const patch = row;
54
- const current = patchMap.get(patch.bundle_id) ?? [];
55
- current.push(patch);
56
- patchMap.set(patch.bundle_id, current);
57
- }
58
- return patchMap;
45
+ const assertPatchReferences = async (client, bundleId, baseBundleId) => {
46
+ const ids = Array.from(new Set([bundleId, baseBundleId]));
47
+ if (await getPrismaDelegate(client, "bundles").count({ where: { id: { in: ids } } }) !== ids.length) throw new PrismaAdapterError("patch references a missing bundle");
48
+ };
49
+ const createCrudImplementation = (client, provider, relationMode) => ({
50
+ deleteChannel: async ({ id }) => {
51
+ const channels = getPrismaDelegate(client, "channels");
52
+ if (await channels.findFirst({ where: { id } }) === null) return {
53
+ deleted: false,
54
+ reason: "not_found"
59
55
  };
60
- const mapRowsToBundles = async (rows) => {
61
- const patchMap = await fetchPatchMap(rows.map((row) => String(row["id"])));
62
- return rows.map((row) => rowToBundle(row, patchMap.get(String(row["id"])) ?? []));
56
+ if (await getPrismaDelegate(client, "releases").count({ where: { channel_id: id } }) > 0) return {
57
+ deleted: false,
58
+ reason: "not_empty"
63
59
  };
64
- const upsertBundle = async (client, bundle) => {
65
- const bundles = getDelegate(client, "bundles");
66
- const patches = getDelegate(client, "bundle_patches");
67
- const row = bundleToRow(bundle);
68
- const { id, ...update } = row;
69
- await bundles.upsert({
70
- where: { id },
71
- create: row,
72
- update
73
- });
74
- await patches.deleteMany({ where: { bundle_id: id } });
75
- const patchRows = bundleToPatchRows(bundle);
76
- if (patchRows.length > 0) await patches.createMany({ data: patchRows });
60
+ try {
61
+ await channels.deleteMany({ where: { id } });
62
+ } catch (error) {
63
+ if (isChannelDeleteReferencedError(error)) return {
64
+ deleted: false,
65
+ reason: "not_empty"
66
+ };
67
+ throw error;
68
+ }
69
+ return { deleted: true };
70
+ },
71
+ insertChannel: async (input) => {
72
+ const delegate = getPrismaDelegate(client, "channels");
73
+ const existing = await delegate.findFirst({ where: { name: input.row.name } });
74
+ if (existing !== null) return {
75
+ row: parsePrismaChannelRow(existing),
76
+ inserted: false
77
77
  };
78
+ const row = parsePrismaChannelRow(await delegate.upsert({
79
+ where: { name: input.row.name },
80
+ create: input.row,
81
+ update: {}
82
+ }));
78
83
  return {
79
- async getBundleById(bundleId) {
80
- const row = await getDelegate(prisma, "bundles").findFirst({ where: { id: bundleId } });
81
- if (!row) return null;
82
- return rowToBundle(row, (await fetchPatchMap([bundleId])).get(bundleId) ?? []);
83
- },
84
- async getBundles(options) {
85
- const bundles = getDelegate(prisma, "bundles");
86
- const offset = options.offset ?? 0;
87
- const orderBy = options.orderBy ?? {
88
- field: "id",
89
- direction: "desc"
90
- };
91
- const where = prismaWhere(options.where);
92
- const [total, rows] = await Promise.all([bundles.count({ where }), bundles.findMany({
93
- where,
94
- orderBy: { id: orderBy.direction },
95
- skip: offset,
96
- take: options.limit
97
- })]);
98
- const patchMap = await fetchPatchMap(rows.map((row) => String(row["id"])));
99
- return {
100
- data: rows.map((row) => rowToBundle(row, patchMap.get(String(row["id"])) ?? [])),
101
- pagination: calculatePagination(total, {
102
- limit: options.limit,
103
- offset
104
- })
105
- };
106
- },
107
- async getUpdateInfo(args, context) {
108
- const bundles = getDelegate(prisma, "bundles");
109
- if (args._updateStrategy === "appVersion") {
110
- const channel = args.channel ?? "production";
111
- const minBundleId = args.minBundleId ?? NIL_UUID;
112
- const rows = await bundles.findMany({
113
- select: { target_app_version: true },
114
- where: {
115
- enabled: true,
116
- platform: args.platform,
117
- channel,
118
- id: { gte: minBundleId },
119
- target_app_version: { not: null }
120
- }
121
- });
122
- const compatibleAppVersions = filterCompatibleAppVersions(Array.from(new Set(rows.map((row) => row["target_app_version"]).filter((value) => typeof value === "string" && value.length > 0))), args.appVersion);
123
- const updateBundles = compatibleAppVersions.length > 0 ? await bundles.findMany({
124
- where: {
125
- enabled: true,
126
- platform: args.platform,
127
- channel,
128
- id: { gte: minBundleId },
129
- target_app_version: { in: compatibleAppVersions }
130
- },
131
- orderBy: { id: "desc" }
132
- }).then(mapRowsToBundles) : [];
133
- return resolveUpdateInfoFromBundles({
134
- args: {
135
- ...args,
136
- channel,
137
- minBundleId
138
- },
139
- bundles: updateBundles,
140
- context
141
- });
142
- }
143
- const channel = args.channel ?? "production";
144
- const minBundleId = args.minBundleId ?? NIL_UUID;
145
- const rows = await bundles.findMany({
146
- where: {
147
- enabled: true,
148
- platform: args.platform,
149
- channel,
150
- id: { gte: minBundleId },
151
- fingerprint_hash: args.fingerprintHash
152
- },
153
- orderBy: { id: "desc" }
154
- });
155
- return resolveUpdateInfoFromBundles({
156
- args: {
157
- ...args,
158
- channel,
159
- minBundleId
160
- },
161
- bundles: await mapRowsToBundles(rows),
162
- context
163
- });
164
- },
165
- async getChannels() {
166
- const rows = await getDelegate(prisma, "bundles").findMany({
167
- select: { channel: true },
168
- orderBy: { channel: "asc" }
169
- });
170
- return Array.from(new Set(rows.map((row) => String(row["channel"]))));
171
- },
172
- async commitBundle({ changedSets }) {
173
- await runInTransaction(async (client) => {
174
- const bundles = getDelegate(client, "bundles");
175
- const patches = getDelegate(client, "bundle_patches");
176
- for (const change of changedSets) {
177
- if (change.operation === "delete") {
178
- await patches.deleteMany({ where: { bundle_id: change.data.id } });
179
- await patches.deleteMany({ where: { base_bundle_id: change.data.id } });
180
- await bundles.deleteMany({ where: { id: change.data.id } });
181
- continue;
182
- }
183
- await upsertBundle(client, change.data);
184
- }
185
- });
186
- }
84
+ row,
85
+ inserted: row.id === input.row.id
187
86
  };
188
- }
87
+ },
88
+ create: async (input) => {
89
+ if (input.model === "bundle_patches") await assertPatchReferences(client, input.data.bundle_id, input.data.base_bundle_id);
90
+ const delegate = getPrismaDelegate(client, input.model);
91
+ let row;
92
+ if (input.onConflict === "ignore") {
93
+ const where = input.model === "channels" ? { name: input.data.name } : { hash: input.data.hash };
94
+ row = await delegate.upsert({
95
+ where,
96
+ create: input.data,
97
+ update: {}
98
+ });
99
+ } else row = await delegate.create({ data: input.data });
100
+ switch (input.model) {
101
+ case "bundles": return parsePrismaBundleRow(row);
102
+ case "bundle_patches": return parsePrismaPatchRow(row);
103
+ case "bundle_events": return parsePrismaBundleEventRow(row);
104
+ case "channels": return parsePrismaChannelRow(row);
105
+ case "api_keys": return parsePrismaApiKeyRow(row);
106
+ case "releases": return parsePrismaReleaseRow(row);
107
+ case "release_catalogs": return parsePrismaReleaseCatalogRow(row);
108
+ }
109
+ },
110
+ update: async (input) => {
111
+ const id = input.where[0]?.value;
112
+ if (typeof id !== "string") throw new PrismaAdapterError(`${input.model} update requires a string id`);
113
+ if (input.model === "api_keys") {
114
+ const delegate = getPrismaDelegate(client, "api_keys");
115
+ if (await delegate.findFirst({ where: { id } }) === null) return null;
116
+ await delegate.update({
117
+ where: { id },
118
+ data: input.update
119
+ });
120
+ const stored = await delegate.findFirst({ where: { id } });
121
+ return stored === null ? null : parsePrismaApiKeyRow(stored);
122
+ }
123
+ if (input.model === "releases") {
124
+ const delegate = getPrismaDelegate(client, "releases");
125
+ if (await delegate.findFirst({ where: { id } }) === null) return null;
126
+ await delegate.update({
127
+ where: { id },
128
+ data: input.update
129
+ });
130
+ const stored = await delegate.findFirst({ where: { id } });
131
+ return stored === null ? null : parsePrismaReleaseRow(stored);
132
+ }
133
+ if (input.model === "release_catalogs") {
134
+ const delegate = getPrismaDelegate(client, "release_catalogs");
135
+ if (await delegate.findFirst({ where: { scope_key: id } }) === null) return null;
136
+ await delegate.update({
137
+ where: { scope_key: id },
138
+ data: input.update
139
+ });
140
+ const stored = await delegate.findFirst({ where: { scope_key: id } });
141
+ return stored === null ? null : parsePrismaReleaseCatalogRow(stored);
142
+ }
143
+ const delegate = getPrismaDelegate(client, "bundles");
144
+ if (delegate.updateMany === void 0) throw new PrismaAdapterError("model delegate \"bundles\" requires updateMany");
145
+ if (await delegate.findFirst({ where: { id } }) === null) return null;
146
+ await delegate.updateMany({
147
+ where: { id },
148
+ data: input.update
149
+ });
150
+ const stored = await delegate.findFirst({ where: { id } });
151
+ if (stored === null) return null;
152
+ return parsePrismaBundleRow(stored);
153
+ },
154
+ delete: async (input) => {
155
+ if (input.model === "bundles" && relationMode === "prisma") {
156
+ const ids = parsePrismaRows(await getPrismaDelegate(client, "bundles").findMany({ where: createPrismaWhere(input.where, provider) }), parsePrismaBundleRow).map(({ id }) => id);
157
+ if (ids.length === 0) return;
158
+ await getPrismaDelegate(client, "bundle_patches").deleteMany({ where: { OR: [{ bundle_id: { in: ids } }, { base_bundle_id: { in: ids } }] } });
159
+ }
160
+ try {
161
+ await getPrismaDelegate(client, input.model).deleteMany({ where: createPrismaWhere(input.where, provider) });
162
+ } catch (error) {
163
+ if (input.model === "channels") translateChannelDeleteError(error);
164
+ throw error;
165
+ }
166
+ },
167
+ count: async (input) => {
168
+ if (input.distinct !== void 0) throw new DatabasePluginInputError("invalid-operation");
169
+ return getPrismaDelegate(client, input.model).count({ where: createPrismaWhere(input.where, provider) });
170
+ },
171
+ findOne: async (input) => {
172
+ const row = await getPrismaDelegate(client, input.model).findFirst({ where: createPrismaWhere(input.where, provider) });
173
+ if (row === null) return null;
174
+ switch (input.model) {
175
+ case "bundles": return parsePrismaBundleRow(row);
176
+ case "bundle_patches": return parsePrismaPatchRow(row);
177
+ case "channels": return parsePrismaChannelRow(row);
178
+ case "api_keys": return parsePrismaApiKeyRow(row);
179
+ case "releases": return parsePrismaReleaseRow(row);
180
+ case "release_catalogs": return parsePrismaReleaseCatalogRow(row);
181
+ }
182
+ },
183
+ findMany: (input) => findMany(client, input, provider)
189
184
  });
185
+ const createPrismaImplementation = (client, relationMode, provider) => {
186
+ const crud = createCrudImplementation(client, provider, relationMode);
187
+ const implementation = {
188
+ ...crud,
189
+ deleteChannel: (input) => {
190
+ if (!hasCallbackTransaction(client)) throw new PrismaAdapterError("channel deletion requires callback transactions");
191
+ return runPrismaTransaction(client, "serializable", (transactionClient) => createCrudImplementation(transactionClient, provider, relationMode).deleteChannel(input));
192
+ },
193
+ delete: (input) => {
194
+ if (input.model !== "bundles" || relationMode === "foreign-keys") return crud.delete(input);
195
+ if (!hasCallbackTransaction(client)) throw new PrismaAdapterError("relation mode \"prisma\" requires callback transactions");
196
+ return runPrismaTransaction(client, "serializable", (transactionClient) => createCrudImplementation(transactionClient, provider, relationMode).delete(input));
197
+ }
198
+ };
199
+ if (relationMode === "prisma" && !hasCallbackTransaction(client)) throw new PrismaAdapterError("relation mode \"prisma\" requires callback transactions");
200
+ if (!hasCallbackTransaction(client)) return implementation;
201
+ if (relationMode === "prisma") implementation.create = (input) => runPrismaTransaction(client, "serializable", (transactionClient) => createCrudImplementation(transactionClient, provider, relationMode).create(input));
202
+ implementation.update = (input) => runPrismaTransaction(client, relationMode === "prisma" ? "serializable" : "default", (transactionClient) => createCrudImplementation(transactionClient, provider, relationMode).update(input));
203
+ return {
204
+ ...implementation,
205
+ transaction: (callback) => runPrismaTransaction(client, "serializable", async (transactionClient) => {
206
+ return callback(createCrudImplementation(transactionClient, provider, relationMode));
207
+ })
208
+ };
209
+ };
190
210
  const prismaAdapter = (config) => {
191
- assertSupportedRelationMode(config.relationMode);
192
- return Object.assign(createPrismaPlugin(config), {
211
+ assertPrismaProvider(config.provider);
212
+ const adapter = createDatabasePluginAdapter("prisma", createPrismaImplementation(config.prisma, config.relationMode ?? "foreign-keys", config.provider));
213
+ return Object.assign(createDatabasePlugin({
214
+ name: "prisma",
215
+ models: adapter.models,
216
+ commit: adapter.commit
217
+ }), {
193
218
  adapterName: "prisma",
194
219
  provider: config.provider,
195
- generateSchema: (version) => ({
220
+ generateSchema: ((version) => ({
196
221
  code: generatePrismaSchema(config.provider, version === "latest" ? hotUpdaterSchema : getHotUpdaterSchemaVersion(version)),
197
222
  path: "./prisma/schema/hot_updater.prisma"
198
- })
223
+ }))
199
224
  });
200
225
  };
201
226
  //#endregion
@@ -0,0 +1,58 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
3
+ //#region src/adapters/prismaQuery.ts
4
+ const stringFilter = (operator, value, mode) => {
5
+ return {
6
+ [operator === "starts_with" ? "startsWith" : operator === "ends_with" ? "endsWith" : "contains"]: value,
7
+ ...mode ? { mode } : {}
8
+ };
9
+ };
10
+ const SQL_PATTERN_METACHARACTERS = /[%_\\]/u;
11
+ const MONGODB_PATTERN_METACHARACTERS = /[.*+?^${}()|[\]\\]/u;
12
+ const prismaMode = (mode, provider) => {
13
+ if (mode === "insensitive" || mode === "sensitive" && provider !== "postgresql") throw new _hot_updater_plugin_core.DatabasePluginInputError("invalid-operation");
14
+ return mode === "sensitive" ? "default" : void 0;
15
+ };
16
+ const assertLiteralPattern = (value, provider) => {
17
+ if ((provider === "mongodb" ? MONGODB_PATTERN_METACHARACTERS : SQL_PATTERN_METACHARACTERS).test(value)) throw new _hot_updater_plugin_core.DatabasePluginInputError("invalid-operation");
18
+ };
19
+ const predicate = (where, provider) => {
20
+ const mode = prismaMode("mode" in where ? where.mode : void 0, provider);
21
+ switch (where.operator) {
22
+ case void 0:
23
+ case "eq": return { [where.field]: mode ? {
24
+ equals: where.value,
25
+ mode
26
+ } : where.value };
27
+ case "ne": return { [where.field]: {
28
+ not: where.value,
29
+ ...mode ? { mode } : {}
30
+ } };
31
+ case "gt":
32
+ case "gte":
33
+ case "lt":
34
+ case "lte": return { [where.field]: { [where.operator]: where.value } };
35
+ case "in": return { [where.field]: { in: where.value } };
36
+ case "not_in": return { [where.field]: { notIn: where.value } };
37
+ case "contains":
38
+ case "starts_with":
39
+ case "ends_with":
40
+ assertLiteralPattern(where.value, provider);
41
+ return { [where.field]: stringFilter(where.operator, where.value, mode) };
42
+ }
43
+ };
44
+ const createPrismaWhere = (where, provider) => {
45
+ const items = where ?? [];
46
+ const first = items[0];
47
+ if (first === void 0) return {};
48
+ let result = predicate(first, provider);
49
+ for (const item of items.slice(1)) result = { [item.connector === "OR" ? "OR" : "AND"]: [result, predicate(item, provider)] };
50
+ return result;
51
+ };
52
+ const createPrismaOrderBy = (orderBy) => {
53
+ if (orderBy === void 0) return void 0;
54
+ return (Array.isArray(orderBy) ? orderBy : [orderBy]).map((clause) => ({ [clause.field]: clause.direction }));
55
+ };
56
+ //#endregion
57
+ exports.createPrismaOrderBy = createPrismaOrderBy;
58
+ exports.createPrismaWhere = createPrismaWhere;
@@ -0,0 +1,56 @@
1
+ import { DatabasePluginInputError } from "@hot-updater/plugin-core";
2
+ //#region src/adapters/prismaQuery.ts
3
+ const stringFilter = (operator, value, mode) => {
4
+ return {
5
+ [operator === "starts_with" ? "startsWith" : operator === "ends_with" ? "endsWith" : "contains"]: value,
6
+ ...mode ? { mode } : {}
7
+ };
8
+ };
9
+ const SQL_PATTERN_METACHARACTERS = /[%_\\]/u;
10
+ const MONGODB_PATTERN_METACHARACTERS = /[.*+?^${}()|[\]\\]/u;
11
+ const prismaMode = (mode, provider) => {
12
+ if (mode === "insensitive" || mode === "sensitive" && provider !== "postgresql") throw new DatabasePluginInputError("invalid-operation");
13
+ return mode === "sensitive" ? "default" : void 0;
14
+ };
15
+ const assertLiteralPattern = (value, provider) => {
16
+ if ((provider === "mongodb" ? MONGODB_PATTERN_METACHARACTERS : SQL_PATTERN_METACHARACTERS).test(value)) throw new DatabasePluginInputError("invalid-operation");
17
+ };
18
+ const predicate = (where, provider) => {
19
+ const mode = prismaMode("mode" in where ? where.mode : void 0, provider);
20
+ switch (where.operator) {
21
+ case void 0:
22
+ case "eq": return { [where.field]: mode ? {
23
+ equals: where.value,
24
+ mode
25
+ } : where.value };
26
+ case "ne": return { [where.field]: {
27
+ not: where.value,
28
+ ...mode ? { mode } : {}
29
+ } };
30
+ case "gt":
31
+ case "gte":
32
+ case "lt":
33
+ case "lte": return { [where.field]: { [where.operator]: where.value } };
34
+ case "in": return { [where.field]: { in: where.value } };
35
+ case "not_in": return { [where.field]: { notIn: where.value } };
36
+ case "contains":
37
+ case "starts_with":
38
+ case "ends_with":
39
+ assertLiteralPattern(where.value, provider);
40
+ return { [where.field]: stringFilter(where.operator, where.value, mode) };
41
+ }
42
+ };
43
+ const createPrismaWhere = (where, provider) => {
44
+ const items = where ?? [];
45
+ const first = items[0];
46
+ if (first === void 0) return {};
47
+ let result = predicate(first, provider);
48
+ for (const item of items.slice(1)) result = { [item.connector === "OR" ? "OR" : "AND"]: [result, predicate(item, provider)] };
49
+ return result;
50
+ };
51
+ const createPrismaOrderBy = (orderBy) => {
52
+ if (orderBy === void 0) return void 0;
53
+ return (Array.isArray(orderBy) ? orderBy : [orderBy]).map((clause) => ({ [clause.field]: clause.direction }));
54
+ };
55
+ //#endregion
56
+ export { createPrismaOrderBy, createPrismaWhere };