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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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/apiKeys.cjs +139 -0
  44. package/dist/apiKeys.d.cts +50 -0
  45. package/dist/apiKeys.d.mts +50 -0
  46. package/dist/apiKeys.mjs +133 -0
  47. package/dist/createHotUpdaterCore.cjs +48 -26
  48. package/dist/createHotUpdaterCore.d.cts +49 -17
  49. package/dist/createHotUpdaterCore.d.mts +49 -17
  50. package/dist/createHotUpdaterCore.mjs +51 -29
  51. package/dist/db/createBundleDiff.cjs +45 -68
  52. package/dist/db/createBundleDiff.d.cts +3 -3
  53. package/dist/db/createBundleDiff.d.mts +3 -3
  54. package/dist/db/createBundleDiff.mjs +47 -68
  55. package/dist/db/databasePluginCore.cjs +138 -0
  56. package/dist/db/databasePluginCore.mjs +137 -0
  57. package/dist/db/fixedMigrator.cjs +36 -93
  58. package/dist/db/fixedMigrator.mjs +36 -93
  59. package/dist/db/fixedMigratorMongo.cjs +319 -0
  60. package/dist/db/fixedMigratorMongo.mjs +319 -0
  61. package/dist/db/fixedMigratorShared.cjs +23 -0
  62. package/dist/db/fixedMigratorShared.mjs +18 -0
  63. package/dist/db/mongoMigrationExecution.cjs +11 -0
  64. package/dist/db/mongoMigrationExecution.mjs +11 -0
  65. package/dist/db/releaseCatalog.cjs +66 -0
  66. package/dist/db/releaseCatalog.d.cts +17 -0
  67. package/dist/db/releaseCatalog.d.mts +17 -0
  68. package/dist/db/releaseCatalog.mjs +64 -0
  69. package/dist/db/schema/mongodb.cjs +14 -6
  70. package/dist/db/schema/mongodb.mjs +14 -6
  71. package/dist/db/schema/registry.cjs +0 -2
  72. package/dist/db/schema/registry.mjs +1 -2
  73. package/dist/db/schema/sql.cjs +31 -14
  74. package/dist/db/schema/sql.mjs +32 -13
  75. package/dist/db/schema/sqlOperations.cjs +4 -4
  76. package/dist/db/schema/sqlOperations.mjs +5 -5
  77. package/dist/db/schemaGenerators.cjs +52 -18
  78. package/dist/db/schemaGenerators.mjs +52 -18
  79. package/dist/db/schemaReadiness.cjs +4 -3
  80. package/dist/db/schemaReadiness.mjs +4 -3
  81. package/dist/db/sqlMigrationExecution.cjs +67 -0
  82. package/dist/db/sqlMigrationExecution.mjs +66 -0
  83. package/dist/db/types.cjs +2 -6
  84. package/dist/db/types.d.cts +60 -16
  85. package/dist/db/types.d.mts +60 -16
  86. package/dist/db/types.mjs +3 -6
  87. package/dist/db/updateArtifacts.cjs +114 -60
  88. package/dist/db/updateArtifacts.mjs +117 -62
  89. package/dist/handler.cjs +108 -282
  90. package/dist/handler.d.cts +3 -46
  91. package/dist/handler.d.mts +3 -46
  92. package/dist/handler.mjs +107 -281
  93. package/dist/handlerBundleRoutes.cjs +155 -0
  94. package/dist/handlerBundleRoutes.mjs +155 -0
  95. package/dist/handlerErrors.cjs +9 -0
  96. package/dist/handlerErrors.mjs +9 -0
  97. package/dist/handlerParameters.cjs +39 -0
  98. package/dist/handlerParameters.mjs +34 -0
  99. package/dist/handlerReleaseCatalogRoutes.cjs +111 -0
  100. package/dist/handlerReleaseCatalogRoutes.mjs +110 -0
  101. package/dist/handlerReleaseManagementRoutes.cjs +125 -0
  102. package/dist/handlerReleaseManagementRoutes.mjs +124 -0
  103. package/dist/handlerTypes.d.cts +63 -0
  104. package/dist/handlerTypes.d.mts +63 -0
  105. package/dist/handlerVersionRoutes.cjs +10 -0
  106. package/dist/handlerVersionRoutes.d.cts +4 -0
  107. package/dist/handlerVersionRoutes.d.mts +4 -0
  108. package/dist/handlerVersionRoutes.mjs +9 -0
  109. package/dist/index.cjs +10 -1
  110. package/dist/index.d.cts +9 -3
  111. package/dist/index.d.mts +9 -3
  112. package/dist/index.mjs +5 -2
  113. package/dist/insights/bounded/activeOverview.cjs +87 -0
  114. package/dist/insights/bounded/activeOverview.mjs +85 -0
  115. package/dist/insights/bounded/installationSearch.cjs +42 -0
  116. package/dist/insights/bounded/installationSearch.mjs +42 -0
  117. package/dist/insights/bounded/persistence.cjs +39 -0
  118. package/dist/insights/bounded/persistence.mjs +38 -0
  119. package/dist/insights/bounded/provider.cjs +170 -0
  120. package/dist/insights/bounded/provider.d.cts +7 -0
  121. package/dist/insights/bounded/provider.d.mts +7 -0
  122. package/dist/insights/bounded/provider.mjs +170 -0
  123. package/dist/insights/bounded/scan.cjs +144 -0
  124. package/dist/insights/bounded/scan.mjs +138 -0
  125. package/dist/insights/domain.d.cts +121 -0
  126. package/dist/insights/domain.d.mts +121 -0
  127. package/dist/insights/errors.cjs +22 -0
  128. package/dist/insights/errors.mjs +20 -0
  129. package/dist/insights/eventInput.cjs +111 -0
  130. package/dist/insights/eventInput.mjs +111 -0
  131. package/dist/insights/persistence.d.cts +6 -0
  132. package/dist/insights/persistence.d.mts +6 -0
  133. package/dist/insights/queryInput.cjs +58 -0
  134. package/dist/insights/queryInput.mjs +55 -0
  135. package/dist/insights/routes.cjs +63 -0
  136. package/dist/insights/routes.mjs +61 -0
  137. package/dist/insights/types.d.cts +17 -0
  138. package/dist/insights/types.d.mts +17 -0
  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/apiKeys.integration.spec.ts +192 -0
  188. package/src/apiKeys.spec.ts +162 -0
  189. package/src/apiKeys.ts +220 -0
  190. package/src/createHotUpdaterCore.ts +164 -100
  191. package/src/db/bundleRows.spec.ts +164 -0
  192. package/src/db/bundleRows.ts +10 -140
  193. package/src/db/createBundleDiff.spec.ts +172 -127
  194. package/src/db/createBundleDiff.ts +91 -110
  195. package/src/db/databasePluginCore.spec.ts +62 -0
  196. package/src/db/databasePluginCore.testFixtures.ts +76 -0
  197. package/src/db/databasePluginCore.ts +185 -0
  198. package/src/db/databasePluginUpdateCheck.bench.ts +107 -0
  199. package/src/db/fixedMigrator.spec.ts +184 -42
  200. package/src/db/fixedMigrator.ts +64 -205
  201. package/src/db/fixedMigratorMongo.spec.ts +192 -0
  202. package/src/db/fixedMigratorMongo.ts +425 -0
  203. package/src/db/fixedMigratorShared.ts +36 -0
  204. package/src/db/hotUpdaterSchema.ts +0 -1
  205. package/src/db/index.spec.ts +333 -1025
  206. package/src/db/mongoMigrationExecution.ts +23 -0
  207. package/src/db/node-sqlite.d.ts +25 -0
  208. package/src/db/releaseCatalog.ts +148 -0
  209. package/src/db/schema/mongodb.ts +20 -6
  210. package/src/db/schema/sql.ts +52 -11
  211. package/src/db/schema/sqlOperations.ts +5 -4
  212. package/src/db/schemaGenerators.ts +107 -23
  213. package/src/db/schemaReadiness.ts +2 -1
  214. package/src/db/sqlMigrationExecution.spec.ts +65 -0
  215. package/src/db/sqlMigrationExecution.ts +108 -0
  216. package/src/db/types.spec.ts +55 -0
  217. package/src/db/types.ts +129 -65
  218. package/src/db/updateArtifacts.spec.ts +359 -0
  219. package/src/db/updateArtifacts.ts +290 -126
  220. package/src/handler-standalone.integration.spec.ts +401 -364
  221. package/src/handler.spec.ts +137 -582
  222. package/src/handler.testFixtures.ts +30 -0
  223. package/src/handler.ts +218 -616
  224. package/src/handlerAuth.integration.spec.ts +33 -0
  225. package/src/handlerBundleRoutes.ts +259 -0
  226. package/src/handlerErrors.ts +7 -0
  227. package/src/handlerManagement.spec.ts +262 -0
  228. package/src/handlerParameters.ts +105 -0
  229. package/src/handlerReleaseCatalogRoutes.ts +154 -0
  230. package/src/handlerReleaseManagementRoutes.ts +213 -0
  231. package/src/handlerTypes.ts +96 -0
  232. package/src/handlerVersionRoutes.ts +12 -0
  233. package/src/index.ts +22 -2
  234. package/src/insights/bounded/activeOverview.spec.ts +189 -0
  235. package/src/insights/bounded/activeOverview.ts +148 -0
  236. package/src/insights/bounded/installationSearch.spec.ts +130 -0
  237. package/src/insights/bounded/installationSearch.ts +69 -0
  238. package/src/insights/bounded/persistence.ts +43 -0
  239. package/src/insights/bounded/provider.spec.ts +219 -0
  240. package/src/insights/bounded/provider.ts +229 -0
  241. package/src/insights/bounded/scan.ts +235 -0
  242. package/src/insights/domain.ts +139 -0
  243. package/src/insights/errors.ts +18 -0
  244. package/src/insights/eventInput.ts +168 -0
  245. package/src/insights/insights.integration.spec.ts +144 -0
  246. package/src/insights/persistence.ts +10 -0
  247. package/src/insights/queryInput.ts +102 -0
  248. package/src/insights/routes.ts +123 -0
  249. package/src/insights/types.ts +44 -0
  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,49 +1,6 @@
1
- import { PaginatedResult } from "./types/index.cjs";
2
- import { AppUpdateAvailableInfo, AppVersionGetBundlesArgs, Bundle, FingerprintGetBundlesArgs } from "@hot-updater/core";
3
- import { DatabaseBundleQueryOptions, HotUpdaterContext } from "@hot-updater/plugin-core";
1
+ import { HandlerAPI, HotUpdaterHandler, HotUpdaterHandlers } from "./handlerTypes.cjs";
4
2
 
5
3
  //#region src/handler.d.ts
6
- interface HandlerAPI<TContext = unknown> {
7
- getAppUpdateInfo: (args: AppVersionGetBundlesArgs | FingerprintGetBundlesArgs, context?: HotUpdaterContext<TContext>) => Promise<AppUpdateAvailableInfo | null>;
8
- getBundleById: (id: string, context?: HotUpdaterContext<TContext>) => Promise<Bundle | null>;
9
- getBundles: (options: DatabaseBundleQueryOptions, context?: HotUpdaterContext<TContext>) => Promise<PaginatedResult>;
10
- insertBundle: (bundle: Bundle, context?: HotUpdaterContext<TContext>) => Promise<void>;
11
- updateBundleById: (bundleId: string, bundle: Partial<Bundle>, context?: HotUpdaterContext<TContext>) => Promise<void>;
12
- deleteBundleById: (bundleId: string, context?: HotUpdaterContext<TContext>) => Promise<void>;
13
- getChannels: (context?: HotUpdaterContext<TContext>) => Promise<string[]>;
14
- }
15
- interface HandlerOptions {
16
- /**
17
- * Base path for all routes
18
- * @default "/api"
19
- */
20
- basePath?: string;
21
- /**
22
- * Route groups to mount. Omit this option to use the default route groups.
23
- * When provided, both route groups must be specified explicitly.
24
- * The `/version` endpoint is always mounted for diagnostics.
25
- */
26
- routes?: HandlerRoutes;
27
- }
28
- interface HandlerRoutes {
29
- /**
30
- * Controls whether update-check routes are mounted.
31
- * Defaults to `true` only when `routes` is omitted.
32
- */
33
- updateCheck: boolean;
34
- /**
35
- * Controls whether bundle management routes are mounted.
36
- * This includes `/api/bundles*`, which are used by the
37
- * CLI `standaloneRepository` plugin.
38
- * Defaults to `false` only when `routes` is omitted.
39
- */
40
- bundles: boolean;
41
- }
42
- /**
43
- * Creates a Web Standard Request handler for Hot Updater API
44
- * This handler is framework-agnostic and works with any runtime that
45
- * supports standard Request/Response objects.
46
- */
47
- declare function createHandler<TContext = unknown>(api: HandlerAPI<TContext>, options?: HandlerOptions): (request: Request, context?: HotUpdaterContext<TContext>) => Promise<Response>;
4
+ declare function createHandlers(api: HandlerAPI): HotUpdaterHandlers;
48
5
  //#endregion
49
- export { HandlerAPI, HandlerOptions, HandlerRoutes, createHandler };
6
+ export { createHandlers };
@@ -1,49 +1,6 @@
1
- import { PaginatedResult } from "./types/index.mjs";
2
- import { DatabaseBundleQueryOptions, HotUpdaterContext } from "@hot-updater/plugin-core";
3
- import { AppUpdateAvailableInfo, AppVersionGetBundlesArgs, Bundle as Bundle$1, FingerprintGetBundlesArgs } from "@hot-updater/core";
1
+ import { HandlerAPI, HotUpdaterHandler, HotUpdaterHandlers } from "./handlerTypes.mjs";
4
2
 
5
3
  //#region src/handler.d.ts
6
- interface HandlerAPI<TContext = unknown> {
7
- getAppUpdateInfo: (args: AppVersionGetBundlesArgs | FingerprintGetBundlesArgs, context?: HotUpdaterContext<TContext>) => Promise<AppUpdateAvailableInfo | null>;
8
- getBundleById: (id: string, context?: HotUpdaterContext<TContext>) => Promise<Bundle$1 | null>;
9
- getBundles: (options: DatabaseBundleQueryOptions, context?: HotUpdaterContext<TContext>) => Promise<PaginatedResult>;
10
- insertBundle: (bundle: Bundle$1, context?: HotUpdaterContext<TContext>) => Promise<void>;
11
- updateBundleById: (bundleId: string, bundle: Partial<Bundle$1>, context?: HotUpdaterContext<TContext>) => Promise<void>;
12
- deleteBundleById: (bundleId: string, context?: HotUpdaterContext<TContext>) => Promise<void>;
13
- getChannels: (context?: HotUpdaterContext<TContext>) => Promise<string[]>;
14
- }
15
- interface HandlerOptions {
16
- /**
17
- * Base path for all routes
18
- * @default "/api"
19
- */
20
- basePath?: string;
21
- /**
22
- * Route groups to mount. Omit this option to use the default route groups.
23
- * When provided, both route groups must be specified explicitly.
24
- * The `/version` endpoint is always mounted for diagnostics.
25
- */
26
- routes?: HandlerRoutes;
27
- }
28
- interface HandlerRoutes {
29
- /**
30
- * Controls whether update-check routes are mounted.
31
- * Defaults to `true` only when `routes` is omitted.
32
- */
33
- updateCheck: boolean;
34
- /**
35
- * Controls whether bundle management routes are mounted.
36
- * This includes `/api/bundles*`, which are used by the
37
- * CLI `standaloneRepository` plugin.
38
- * Defaults to `false` only when `routes` is omitted.
39
- */
40
- bundles: boolean;
41
- }
42
- /**
43
- * Creates a Web Standard Request handler for Hot Updater API
44
- * This handler is framework-agnostic and works with any runtime that
45
- * supports standard Request/Response objects.
46
- */
47
- declare function createHandler<TContext = unknown>(api: HandlerAPI<TContext>, options?: HandlerOptions): (request: Request, context?: HotUpdaterContext<TContext>) => Promise<Response>;
4
+ declare function createHandlers(api: HandlerAPI): HotUpdaterHandlers;
48
5
  //#endregion
49
- export { HandlerAPI, HandlerOptions, HandlerRoutes, createHandler };
6
+ export { createHandlers };
package/dist/handler.mjs CHANGED
@@ -1,293 +1,119 @@
1
+ import { HandlerBadRequestError } from "./handlerErrors.mjs";
2
+ import { createBundleRouteHandlers } from "./handlerBundleRoutes.mjs";
3
+ import { createReleaseCatalogRouteHandlers } from "./handlerReleaseCatalogRoutes.mjs";
4
+ import { createReleaseManagementRouteHandlers } from "./handlerReleaseManagementRoutes.mjs";
5
+ import { createVersionRouteHandlers } from "./handlerVersionRoutes.mjs";
6
+ import { createInsightsRouteHandlers, registerInsightsAdminRoutes, registerInsightsClientRoutes } from "./insights/routes.mjs";
1
7
  import { addRoute, createRouter, findRoute } from "./internalRouter.mjs";
2
- import { HOT_UPDATER_SERVER_VERSION } from "./version.mjs";
3
- import { isGreaterOrEqual, normalize } from "verkit";
4
8
  //#region src/handler.ts
5
- var HandlerBadRequestError = class extends Error {
6
- constructor(message) {
7
- super(message);
8
- this.name = "HandlerBadRequestError";
9
- }
10
- };
11
- const SDK_VERSION_HEADER = "Hot-Updater-SDK-Version";
12
- const EXPLICIT_NO_UPDATE_MIN_SDK_VERSION = "0.31.0";
13
- const DEFAULT_BUNDLE_LIST_LIMIT = 50;
14
- const MAX_BUNDLE_LIST_LIMIT = 100;
15
- const supportsExplicitNoUpdateResponse = (request) => {
16
- const sdkVersion = request.headers.get(SDK_VERSION_HEADER)?.trim();
17
- if (!sdkVersion) return false;
18
- const normalizedSdkVersion = normalize(sdkVersion);
19
- return normalizedSdkVersion !== null && isGreaterOrEqual(normalizedSdkVersion, EXPLICIT_NO_UPDATE_MIN_SDK_VERSION);
20
- };
21
- const serializeUpdateInfo = (updateInfo, request) => {
22
- if (updateInfo) return JSON.stringify(updateInfo);
23
- if (supportsExplicitNoUpdateResponse(request)) return JSON.stringify({ status: "UP_TO_DATE" });
24
- return JSON.stringify(null);
25
- };
26
- const handleVersion = async () => {
27
- return new Response(JSON.stringify({ version: HOT_UPDATER_SERVER_VERSION }), {
28
- status: 200,
29
- headers: { "Content-Type": "application/json" }
9
+ const withPrivateNoStore = (response) => {
10
+ const headers = new Headers(response.headers);
11
+ headers.set("cache-control", "private, no-store");
12
+ return new Response(response.body, {
13
+ headers,
14
+ status: response.status,
15
+ statusText: response.statusText
30
16
  });
31
17
  };
32
- const decodeMaybe = (value) => {
33
- if (value === void 0) return void 0;
18
+ const errorResponse = (error, status) => Response.json({ error }, {
19
+ headers: { "cache-control": "private, no-store" },
20
+ status
21
+ });
22
+ const requiresApiKey = (handlerName) => handlerName === "appVersionReleaseCatalog" || handlerName === "fingerprintReleaseCatalog" || handlerName === "artifact" || handlerName === "appendBundleEvent";
23
+ const createRequestHandler = ({ api, apiKeyAuth, privateResponses = false, routeHandlers, router }) => async (request) => {
34
24
  try {
35
- return decodeURIComponent(value);
36
- } catch {
37
- return value;
25
+ const match = findRoute(router, request.method, new URL(request.url).pathname);
26
+ if (!match) return errorResponse("Not found", 404);
27
+ if (apiKeyAuth !== void 0 && requiresApiKey(match.data)) {
28
+ let authenticated;
29
+ try {
30
+ authenticated = await apiKeyAuth.authenticate(request);
31
+ } catch {
32
+ return errorResponse("Service unavailable", 503);
33
+ }
34
+ if (!authenticated) return errorResponse("Unauthorized", 401);
35
+ }
36
+ const handler = routeHandlers[match.data];
37
+ if (!handler) return errorResponse("Handler not found", 500);
38
+ const response = await handler(match.params, request, api);
39
+ return privateResponses ? withPrivateNoStore(response) : response;
40
+ } catch (error) {
41
+ if (error instanceof HandlerBadRequestError) return errorResponse(error.message, 400);
42
+ console.error("Hot Updater handler error:", error);
43
+ return Response.json({ error: "Internal server error" }, {
44
+ headers: { "cache-control": "private, no-store" },
45
+ status: 500
46
+ });
38
47
  }
39
48
  };
40
- const isPlatform = (value) => {
41
- return value === "ios" || value === "android";
42
- };
43
- const requireRouteParam = (params, key) => {
44
- const value = params[key];
45
- if (!value) throw new HandlerBadRequestError(`Missing route parameter: ${key}`);
46
- return value;
47
- };
48
- const parseBooleanSearchParam = (url, key) => {
49
- const value = url.searchParams.get(key);
50
- if (value === null) return;
51
- if (value === "true") return true;
52
- if (value === "false") return false;
53
- throw new HandlerBadRequestError(`The '${key}' query parameter must be 'true' or 'false'.`);
54
- };
55
- const parseNullableStringSearchParam = (url, key) => {
56
- const value = url.searchParams.get(key);
57
- if (value === null) return;
58
- return value === "null" ? null : value;
59
- };
60
- const parseStringArraySearchParam = (url, key) => {
61
- const values = url.searchParams.getAll(key);
62
- return values.length > 0 ? values : void 0;
63
- };
64
- const parsePositiveIntegerSearchParam = (url, key, defaultValue, maxValue) => {
65
- const value = url.searchParams.get(key);
66
- if (value === null) return defaultValue;
67
- const parsed = Number(value);
68
- if (!Number.isInteger(parsed) || parsed < 1 || parsed > maxValue) throw new HandlerBadRequestError(`The '${key}' query parameter must be a positive integer between 1 and ${maxValue}.`);
69
- return parsed;
70
- };
71
- const requirePlatformParam = (params) => {
72
- const platform = requireRouteParam(params, "platform");
73
- if (!isPlatform(platform)) throw new HandlerBadRequestError(`Invalid platform: ${platform}. Expected 'ios' or 'android'.`);
74
- return platform;
75
- };
76
- const requireBundlePatchPayload = (payload, bundleId) => {
77
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) throw new HandlerBadRequestError("Invalid bundle payload");
78
- const bundlePatch = payload;
79
- if (bundlePatch.id !== void 0 && bundlePatch.id !== bundleId) throw new HandlerBadRequestError("Bundle id mismatch");
80
- const { id: _ignoredId, ...rest } = bundlePatch;
81
- return rest;
82
- };
83
- const handleFingerprintUpdateWithCohort = async (params, request, api, context) => {
84
- const platform = requirePlatformParam(params);
85
- const fingerprintHash = requireRouteParam(params, "fingerprintHash");
86
- const channel = requireRouteParam(params, "channel");
87
- const minBundleId = requireRouteParam(params, "minBundleId");
88
- const bundleId = requireRouteParam(params, "bundleId");
89
- const updateInfo = await api.getAppUpdateInfo({
90
- _updateStrategy: "fingerprint",
91
- platform,
92
- fingerprintHash,
93
- channel,
94
- minBundleId,
95
- bundleId,
96
- cohort: decodeMaybe(params.cohort)
97
- }, context);
98
- return new Response(serializeUpdateInfo(updateInfo, request), {
99
- status: 200,
100
- headers: { "Content-Type": "application/json" }
101
- });
102
- };
103
- const handleAppVersionUpdateWithCohort = async (params, request, api, context) => {
104
- const platform = requirePlatformParam(params);
105
- const appVersion = requireRouteParam(params, "appVersion");
106
- const channel = requireRouteParam(params, "channel");
107
- const minBundleId = requireRouteParam(params, "minBundleId");
108
- const bundleId = requireRouteParam(params, "bundleId");
109
- const updateInfo = await api.getAppUpdateInfo({
110
- _updateStrategy: "appVersion",
111
- platform,
112
- appVersion,
113
- channel,
114
- minBundleId,
115
- bundleId,
116
- cohort: decodeMaybe(params.cohort)
117
- }, context);
118
- return new Response(serializeUpdateInfo(updateInfo, request), {
119
- status: 200,
120
- headers: { "Content-Type": "application/json" }
121
- });
122
- };
123
- const handleGetBundle = async (params, _request, api, context) => {
124
- const bundleId = requireRouteParam(params, "id");
125
- const bundle = await api.getBundleById(bundleId, context);
126
- if (!bundle) return new Response(JSON.stringify({ error: "Bundle not found" }), {
127
- status: 404,
128
- headers: { "Content-Type": "application/json" }
129
- });
130
- return new Response(JSON.stringify(bundle), {
131
- status: 200,
132
- headers: { "Content-Type": "application/json" }
49
+ const createDownloadStorageRouteHandler = (downloadStorageObject) => async (params) => {
50
+ const token = params.token;
51
+ const signature = params.signature;
52
+ if (!token || !signature) return errorResponse("Not found", 404);
53
+ const response = await downloadStorageObject(token, signature);
54
+ if (!response) return errorResponse("Not found", 404);
55
+ const headers = new Headers(response.headers);
56
+ if (!headers.has("cache-control")) headers.set("cache-control", "public, max-age=31536000, immutable");
57
+ return new Response(response.body, {
58
+ headers,
59
+ status: response.status,
60
+ statusText: response.statusText
133
61
  });
134
62
  };
135
- const handleGetBundles = async (_params, request, api, context) => {
136
- const url = new URL(request.url);
137
- const channel = url.searchParams.get("channel") ?? void 0;
138
- const platform = url.searchParams.get("platform");
139
- const limit = parsePositiveIntegerSearchParam(url, "limit", DEFAULT_BUNDLE_LIST_LIMIT, MAX_BUNDLE_LIST_LIMIT);
140
- const pageParam = url.searchParams.get("page");
141
- const offset = url.searchParams.get("offset");
142
- const after = url.searchParams.get("after") ?? void 0;
143
- const before = url.searchParams.get("before") ?? void 0;
144
- const enabled = parseBooleanSearchParam(url, "enabled");
145
- const targetAppVersion = parseNullableStringSearchParam(url, "targetAppVersion");
146
- const targetAppVersionIn = parseStringArraySearchParam(url, "targetAppVersionIn");
147
- const targetAppVersionNotNull = parseBooleanSearchParam(url, "targetAppVersionNotNull");
148
- const fingerprintHash = parseNullableStringSearchParam(url, "fingerprintHash");
149
- const idEq = url.searchParams.get("idEq") ?? void 0;
150
- const idGt = url.searchParams.get("idGt") ?? void 0;
151
- const idGte = url.searchParams.get("idGte") ?? void 0;
152
- const idLt = url.searchParams.get("idLt") ?? void 0;
153
- const idLte = url.searchParams.get("idLte") ?? void 0;
154
- const idIn = parseStringArraySearchParam(url, "idIn");
155
- const page = pageParam === null ? void 0 : Number.isInteger(Number(pageParam)) && Number(pageParam) > 0 ? Number(pageParam) : null;
156
- if (offset !== null) throw new HandlerBadRequestError("The 'offset' query parameter has been removed. Use 'after' or 'before' cursor pagination instead.");
157
- if (page === null) throw new HandlerBadRequestError("The 'page' query parameter must be a positive integer.");
158
- if (platform !== null && !isPlatform(platform)) throw new HandlerBadRequestError(`Invalid platform: ${platform}. Expected 'ios' or 'android'.`);
159
- const result = await api.getBundles({
160
- where: {
161
- ...channel && { channel },
162
- ...platform && { platform },
163
- ...enabled !== void 0 && { enabled },
164
- ...idEq || idGt || idGte || idLt || idLte || idIn && idIn.length > 0 ? { id: {
165
- ...idEq && { eq: idEq },
166
- ...idGt && { gt: idGt },
167
- ...idGte && { gte: idGte },
168
- ...idLt && { lt: idLt },
169
- ...idLte && { lte: idLte },
170
- ...idIn && idIn.length > 0 && { in: idIn }
171
- } } : {},
172
- ...targetAppVersion !== void 0 && { targetAppVersion },
173
- ...targetAppVersionIn && { targetAppVersionIn },
174
- ...targetAppVersionNotNull !== void 0 && { targetAppVersionNotNull },
175
- ...fingerprintHash !== void 0 && { fingerprintHash }
176
- },
177
- limit,
178
- page,
179
- cursor: after || before ? {
180
- after,
181
- before
182
- } : void 0
183
- }, context);
184
- return new Response(JSON.stringify(result), {
185
- status: 200,
186
- headers: { "Content-Type": "application/json" }
187
- });
188
- };
189
- const handleCreateBundles = async (_params, request, api, context) => {
190
- const body = await request.json();
191
- const bundles = Array.isArray(body) ? body : [body];
192
- for (const bundle of bundles) await api.insertBundle(bundle, context);
193
- return new Response(JSON.stringify({ success: true }), {
194
- status: 201,
195
- headers: { "Content-Type": "application/json" }
196
- });
197
- };
198
- const handleUpdateBundle = async (params, request, api, context) => {
199
- const bundleId = requireRouteParam(params, "id");
200
- const body = await request.json();
201
- const bundlePatch = requireBundlePatchPayload(Array.isArray(body) ? body[0] : body, bundleId);
202
- await api.updateBundleById(bundleId, bundlePatch, context);
203
- return new Response(JSON.stringify({ success: true }), {
204
- status: 200,
205
- headers: { "Content-Type": "application/json" }
206
- });
207
- };
208
- const handleDeleteBundle = async (params, _request, api, context) => {
209
- const bundleId = requireRouteParam(params, "id");
210
- await api.deleteBundleById(bundleId, context);
211
- return new Response(JSON.stringify({ success: true }), {
212
- status: 200,
213
- headers: { "Content-Type": "application/json" }
214
- });
215
- };
216
- const handleGetChannels = async (_params, _request, api, context) => {
217
- const response = { data: { channels: await api.getChannels(context) } };
218
- return new Response(JSON.stringify(response), {
219
- status: 200,
220
- headers: { "Content-Type": "application/json" }
221
- });
222
- };
223
- const routes = {
224
- version: handleVersion,
225
- fingerprintUpdateWithCohort: handleFingerprintUpdateWithCohort,
226
- appVersionUpdateWithCohort: handleAppVersionUpdateWithCohort,
227
- getBundle: handleGetBundle,
228
- getBundles: handleGetBundles,
229
- createBundles: handleCreateBundles,
230
- updateBundle: handleUpdateBundle,
231
- deleteBundle: handleDeleteBundle,
232
- getChannels: handleGetChannels
233
- };
234
- /**
235
- * Creates a Web Standard Request handler for Hot Updater API
236
- * This handler is framework-agnostic and works with any runtime that
237
- * supports standard Request/Response objects.
238
- */
239
- function createHandler(api, options = {}) {
240
- const basePath = options.basePath ?? "/api";
241
- const routeOptions = {
242
- updateCheck: options.routes?.updateCheck ?? true,
243
- bundles: options.routes?.bundles ?? false
244
- };
245
- const router = createRouter();
246
- addRoute(router, "GET", "/version", "version");
247
- if (routeOptions.updateCheck) {
248
- addRoute(router, "GET", "/fingerprint/:platform/:fingerprintHash/:channel/:minBundleId/:bundleId", "fingerprintUpdateWithCohort");
249
- addRoute(router, "GET", "/fingerprint/:platform/:fingerprintHash/:channel/:minBundleId/:bundleId/:cohort", "fingerprintUpdateWithCohort");
250
- addRoute(router, "GET", "/app-version/:platform/:appVersion/:channel/:minBundleId/:bundleId", "appVersionUpdateWithCohort");
251
- addRoute(router, "GET", "/app-version/:platform/:appVersion/:channel/:minBundleId/:bundleId/:cohort", "appVersionUpdateWithCohort");
252
- }
253
- if (routeOptions.bundles) {
254
- addRoute(router, "GET", "/api/bundles/channels", "getChannels");
255
- addRoute(router, "GET", "/api/bundles/:id", "getBundle");
256
- addRoute(router, "GET", "/api/bundles", "getBundles");
257
- addRoute(router, "POST", "/api/bundles", "createBundles");
258
- addRoute(router, "PATCH", "/api/bundles/:id", "updateBundle");
259
- addRoute(router, "DELETE", "/api/bundles/:id", "deleteBundle");
260
- }
261
- return async (request, context) => {
262
- try {
263
- const path = new URL(request.url).pathname;
264
- const method = request.method;
265
- const match = findRoute(router, method, path.startsWith(basePath) ? path.slice(basePath.length) : path);
266
- if (!match) return new Response(JSON.stringify({ error: "Not found" }), {
267
- status: 404,
268
- headers: { "Content-Type": "application/json" }
269
- });
270
- const handler = routes[match.data];
271
- if (!handler) return new Response(JSON.stringify({ error: "Handler not found" }), {
272
- status: 500,
273
- headers: { "Content-Type": "application/json" }
274
- });
275
- return await handler(match.params || {}, request, api, context);
276
- } catch (error) {
277
- if (error instanceof HandlerBadRequestError) return new Response(JSON.stringify({ error: error.message }), {
278
- status: 400,
279
- headers: { "Content-Type": "application/json" }
280
- });
281
- console.error("Hot Updater handler error:", error);
282
- return new Response(JSON.stringify({
283
- error: "Internal server error",
284
- message: error instanceof Error ? error.message : "Unknown error"
285
- }), {
286
- status: 500,
287
- headers: { "Content-Type": "application/json" }
288
- });
289
- }
63
+ function createHandlers(api) {
64
+ return createHotUpdaterHandlers(api);
65
+ }
66
+ function createHotUpdaterHandlers(api, insights, apiKeyAuth, downloadStorageObject) {
67
+ const routeHandlers = {
68
+ ...createVersionRouteHandlers(),
69
+ ...createReleaseCatalogRouteHandlers(apiKeyAuth?.headerName),
70
+ ...createReleaseManagementRouteHandlers(),
71
+ ...createBundleRouteHandlers(),
72
+ ...insights === void 0 ? {} : createInsightsRouteHandlers(insights),
73
+ ...downloadStorageObject === void 0 ? {} : { downloadStorageObject: createDownloadStorageRouteHandler(downloadStorageObject) }
290
74
  };
75
+ const clientRouter = createRouter();
76
+ const addClientRoute = (method, path, handler) => addRoute(clientRouter, method, path, handler);
77
+ addClientRoute("GET", "/version", "version");
78
+ if (downloadStorageObject !== void 0) addClientRoute("GET", "/storage/:token/:signature", "downloadStorageObject");
79
+ addClientRoute("GET", "/release-catalogs/app-version/:platform/:channelKey/:appVersion", "appVersionReleaseCatalog");
80
+ addClientRoute("GET", "/release-catalogs/fingerprint/:platform/:channelKey/:fingerprintHash", "fingerprintReleaseCatalog");
81
+ addClientRoute("GET", "/artifacts/:targetBundleId/from/:currentBundleId", "artifact");
82
+ if (insights !== void 0) registerInsightsClientRoutes(addClientRoute);
83
+ const adminRouter = createRouter();
84
+ const addAdminRoute = (method, path, handler) => addRoute(adminRouter, method, path, handler);
85
+ addAdminRoute("GET", "/releases/:id", "getRelease");
86
+ addAdminRoute("GET", "/releases", "getReleases");
87
+ addAdminRoute("PATCH", "/releases/:id", "updateRelease");
88
+ addAdminRoute("POST", "/releases/:id/preflight", "preflightRelease");
89
+ addAdminRoute("DELETE", "/releases/:id", "deleteRelease");
90
+ addAdminRoute("GET", "/release-catalogs/:scopeKey", "getReleaseCatalogRow");
91
+ addAdminRoute("GET", "/release-catalogs", "getReleaseCatalogs");
92
+ addAdminRoute("POST", "/release-catalogs/:scopeKey/rebuild", "rebuildReleaseCatalog");
93
+ addAdminRoute("POST", "/database/commit", "commitDatabase");
94
+ addAdminRoute("GET", "/channels", "getChannels");
95
+ addAdminRoute("POST", "/channels", "createChannel");
96
+ addAdminRoute("DELETE", "/channels/:id", "deleteChannel");
97
+ addAdminRoute("GET", "/bundles/:id", "getBundle");
98
+ addAdminRoute("GET", "/bundles", "getBundles");
99
+ addAdminRoute("POST", "/bundles", "createBundles");
100
+ addAdminRoute("PATCH", "/bundles/:id", "updateBundle");
101
+ addAdminRoute("DELETE", "/bundles/:id", "deleteBundle");
102
+ if (insights !== void 0) registerInsightsAdminRoutes(addAdminRoute);
103
+ return Object.freeze({
104
+ client: createRequestHandler({
105
+ api,
106
+ apiKeyAuth,
107
+ routeHandlers,
108
+ router: clientRouter
109
+ }),
110
+ admin: createRequestHandler({
111
+ api,
112
+ privateResponses: true,
113
+ routeHandlers,
114
+ router: adminRouter
115
+ })
116
+ });
291
117
  }
292
118
  //#endregion
293
- export { createHandler };
119
+ export { createHandlers, createHotUpdaterHandlers };
@@ -0,0 +1,155 @@
1
+ const require_handlerErrors = require("./handlerErrors.cjs");
2
+ const require_handlerParameters = require("./handlerParameters.cjs");
3
+ //#region src/handlerBundleRoutes.ts
4
+ const BUNDLE_LIST_BOUNDS = {
5
+ defaultValue: 50,
6
+ maxValue: 100
7
+ };
8
+ const isChannelText = (value) => {
9
+ if (typeof value !== "string" || value.length === 0) return false;
10
+ let codePoints = 0;
11
+ for (const _codePoint of value) {
12
+ codePoints += 1;
13
+ if (codePoints > 255) return false;
14
+ }
15
+ return true;
16
+ };
17
+ const requireChannelInsertInput = (value) => {
18
+ if (!value || typeof value !== "object" || Array.isArray(value) || !("row" in value) || !value.row || typeof value.row !== "object" || Array.isArray(value.row) || !("id" in value.row) || !isChannelText(value.row.id) || !("name" in value.row) || !isChannelText(value.row.name) || !("onConflict" in value) || value.onConflict !== "returnExisting") throw new require_handlerErrors.HandlerBadRequestError("Invalid Channel insert payload");
19
+ return {
20
+ row: {
21
+ id: value.row.id,
22
+ name: value.row.name
23
+ },
24
+ onConflict: value.onConflict
25
+ };
26
+ };
27
+ const requireBundlePatchPayload = (payload, bundleId) => {
28
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) throw new require_handlerErrors.HandlerBadRequestError("Invalid bundle payload");
29
+ const bundlePatch = payload;
30
+ if (bundlePatch.id !== void 0 && bundlePatch.id !== bundleId) throw new require_handlerErrors.HandlerBadRequestError("Bundle id mismatch");
31
+ const { id: _ignoredId, ...rest } = bundlePatch;
32
+ return rest;
33
+ };
34
+ const createBundleRouteHandlers = () => ({
35
+ getBundle: async (params, _request, api) => {
36
+ const bundle = await api.getBundleById(require_handlerParameters.requireRouteParam(params, "id"));
37
+ if (!bundle) return new Response(JSON.stringify({ error: "Bundle not found" }), {
38
+ status: 404,
39
+ headers: { "Content-Type": "application/json" }
40
+ });
41
+ return new Response(JSON.stringify(bundle), {
42
+ status: 200,
43
+ headers: { "Content-Type": "application/json" }
44
+ });
45
+ },
46
+ getBundles: async (_params, request, api) => {
47
+ const url = new URL(request.url);
48
+ const platform = url.searchParams.get("platform");
49
+ const limit = require_handlerParameters.parsePositiveIntegerSearchParam(url, "limit", BUNDLE_LIST_BOUNDS);
50
+ const pageParam = url.searchParams.get("page");
51
+ const offset = url.searchParams.get("offset");
52
+ const after = url.searchParams.get("after") ?? void 0;
53
+ const before = url.searchParams.get("before") ?? void 0;
54
+ const orderDirection = url.searchParams.get("orderDirection");
55
+ const idEq = url.searchParams.get("idEq") ?? void 0;
56
+ const idGt = url.searchParams.get("idGt") ?? void 0;
57
+ const idGte = url.searchParams.get("idGte") ?? void 0;
58
+ const idLt = url.searchParams.get("idLt") ?? void 0;
59
+ const idLte = url.searchParams.get("idLte") ?? void 0;
60
+ const idIn = require_handlerParameters.parseStringArraySearchParam(url, "idIn");
61
+ const page = pageParam === null ? void 0 : Number.isSafeInteger(Number(pageParam)) && Number(pageParam) > 0 && Number.isSafeInteger((Number(pageParam) - 1) * limit) ? Number(pageParam) : null;
62
+ if (offset !== null) throw new require_handlerErrors.HandlerBadRequestError("The 'offset' query parameter has been removed. Use 'after' or 'before' cursor pagination instead.");
63
+ if (page === null) throw new require_handlerErrors.HandlerBadRequestError("The 'page' query parameter must be a positive integer.");
64
+ if (after !== void 0 && before !== void 0) throw new require_handlerErrors.HandlerBadRequestError("The 'after' and 'before' query parameters cannot be combined.");
65
+ if (page !== void 0 && (after !== void 0 || before !== void 0)) throw new require_handlerErrors.HandlerBadRequestError("The 'page' query parameter cannot be combined with 'after' or 'before'.");
66
+ if (platform !== null && !require_handlerParameters.isPlatform(platform)) throw new require_handlerErrors.HandlerBadRequestError(`Invalid platform: ${platform}. Expected 'ios' or 'android'.`);
67
+ if (orderDirection !== null && orderDirection !== "asc" && orderDirection !== "desc") throw new require_handlerErrors.HandlerBadRequestError("The 'orderDirection' query parameter must be 'asc' or 'desc'.");
68
+ const pagination = page === void 0 ? {
69
+ cursor: after !== void 0 ? { after } : before !== void 0 ? { before } : void 0,
70
+ page: void 0
71
+ } : {
72
+ cursor: void 0,
73
+ page
74
+ };
75
+ const result = await api.getBundles({
76
+ where: {
77
+ ...platform && { platform },
78
+ ...idEq || idGt || idGte || idLt || idLte || idIn?.length ? { id: {
79
+ ...idEq && { eq: idEq },
80
+ ...idGt && { gt: idGt },
81
+ ...idGte && { gte: idGte },
82
+ ...idLt && { lt: idLt },
83
+ ...idLte && { lte: idLte },
84
+ ...idIn?.length && { in: idIn }
85
+ } } : {}
86
+ },
87
+ limit,
88
+ ...pagination,
89
+ ...orderDirection && { orderBy: {
90
+ field: "id",
91
+ direction: orderDirection
92
+ } }
93
+ });
94
+ return new Response(JSON.stringify(result), {
95
+ status: 200,
96
+ headers: { "Content-Type": "application/json" }
97
+ });
98
+ },
99
+ createBundles: async (_params, request, api) => {
100
+ const body = await request.json();
101
+ const bundles = Array.isArray(body) ? body : [body];
102
+ if (api.insertBundles) await api.insertBundles(bundles);
103
+ else {
104
+ if (bundles.length > 1) throw new require_handlerErrors.HandlerBadRequestError("This server does not support atomic bundle batches");
105
+ const bundle = bundles[0];
106
+ if (bundle !== void 0) await api.insertBundle(bundle);
107
+ }
108
+ return new Response(JSON.stringify({ success: true }), {
109
+ status: 201,
110
+ headers: { "Content-Type": "application/json" }
111
+ });
112
+ },
113
+ updateBundle: async (params, request, api) => {
114
+ const bundleId = require_handlerParameters.requireRouteParam(params, "id");
115
+ const body = await request.json();
116
+ const payload = Array.isArray(body) ? body[0] : body;
117
+ await api.updateBundleById(bundleId, requireBundlePatchPayload(payload, bundleId));
118
+ return new Response(JSON.stringify({ success: true }), {
119
+ status: 200,
120
+ headers: { "Content-Type": "application/json" }
121
+ });
122
+ },
123
+ deleteBundle: async (params, _request, api) => {
124
+ await api.deleteBundleById(require_handlerParameters.requireRouteParam(params, "id"));
125
+ return new Response(JSON.stringify({ success: true }), {
126
+ status: 200,
127
+ headers: { "Content-Type": "application/json" }
128
+ });
129
+ },
130
+ getChannels: async (_params, _request, api) => {
131
+ const response = { data: { channels: await api.getChannels() } };
132
+ return new Response(JSON.stringify(response), {
133
+ status: 200,
134
+ headers: { "Content-Type": "application/json" }
135
+ });
136
+ },
137
+ createChannel: async (_params, request, api) => {
138
+ const result = await api.insertChannel(requireChannelInsertInput(await request.json()));
139
+ return new Response(JSON.stringify({ data: result }), {
140
+ status: result.inserted ? 201 : 200,
141
+ headers: { "Content-Type": "application/json" }
142
+ });
143
+ },
144
+ deleteChannel: async (params, _request, api) => {
145
+ const result = await api.deleteChannel({ id: require_handlerParameters.decodeMaybe(require_handlerParameters.requireRouteParam(params, "id")) ?? "" });
146
+ if (result.deleted) return new Response(null, { status: 204 });
147
+ const status = result.reason === "not_found" ? 404 : 409;
148
+ return new Response(JSON.stringify({ data: result }), {
149
+ status,
150
+ headers: { "Content-Type": "application/json" }
151
+ });
152
+ }
153
+ });
154
+ //#endregion
155
+ exports.createBundleRouteHandlers = createBundleRouteHandlers;