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

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 (213) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +1 -1
  2. package/dist/adapters/databaseConstraintErrors.cjs +0 -1
  3. package/dist/adapters/databasePluginUtils.cjs +14 -1
  4. package/dist/adapters/databasePluginUtils.mjs +14 -2
  5. package/dist/adapters/drizzle.cjs +9 -4
  6. package/dist/adapters/drizzle.d.cts +0 -1
  7. package/dist/adapters/drizzle.d.mts +0 -1
  8. package/dist/adapters/drizzle.mjs +10 -4
  9. package/dist/adapters/drizzleCrud.cjs +93 -3
  10. package/dist/adapters/drizzleCrud.mjs +93 -5
  11. package/dist/adapters/drizzleLazyDB.cjs +2 -0
  12. package/dist/adapters/drizzleLazyDB.mjs +2 -0
  13. package/dist/adapters/drizzleQuery.cjs +3 -2
  14. package/dist/adapters/drizzleQuery.mjs +3 -1
  15. package/dist/adapters/kysely.cjs +1 -1
  16. package/dist/adapters/kysely.d.cts +0 -1
  17. package/dist/adapters/kysely.d.mts +0 -1
  18. package/dist/adapters/kysely.mjs +2 -1
  19. package/dist/adapters/kyselyCrud.cjs +44 -5
  20. package/dist/adapters/kyselyCrud.mjs +45 -6
  21. package/dist/adapters/kyselyQuery.cjs +2 -2
  22. package/dist/adapters/kyselyQuery.mjs +2 -1
  23. package/dist/adapters/mongodb.cjs +36 -1
  24. package/dist/adapters/mongodb.d.cts +1 -1
  25. package/dist/adapters/mongodb.d.mts +1 -1
  26. package/dist/adapters/mongodb.mjs +36 -0
  27. package/dist/adapters/mongodbCollections.cjs +2 -0
  28. package/dist/adapters/mongodbCollections.mjs +2 -0
  29. package/dist/adapters/mongodbQuery.cjs +17 -4
  30. package/dist/adapters/mongodbQuery.mjs +17 -4
  31. package/dist/adapters/mongodbReads.cjs +88 -30
  32. package/dist/adapters/mongodbReads.mjs +88 -29
  33. package/dist/adapters/mongodbWrites.cjs +1 -2
  34. package/dist/adapters/mongodbWrites.mjs +1 -1
  35. package/dist/adapters/prisma.cjs +44 -7
  36. package/dist/adapters/prisma.d.cts +0 -1
  37. package/dist/adapters/prisma.d.mts +0 -1
  38. package/dist/adapters/prisma.mjs +44 -6
  39. package/dist/adapters/prismaInsights.cjs +99 -0
  40. package/dist/adapters/prismaInsights.mjs +97 -0
  41. package/dist/adapters/prismaQuery.cjs +0 -1
  42. package/dist/adapters/prismaRows.cjs +7 -8
  43. package/dist/adapters/prismaRows.mjs +8 -8
  44. package/dist/apiKeys.cjs +6 -2
  45. package/dist/apiKeys.d.cts +0 -1
  46. package/dist/apiKeys.d.mts +0 -1
  47. package/dist/apiKeys.mjs +3 -3
  48. package/dist/createHotUpdaterCore.cjs +27 -12
  49. package/dist/createHotUpdaterCore.d.cts +8 -8
  50. package/dist/createHotUpdaterCore.d.mts +8 -8
  51. package/dist/createHotUpdaterCore.mjs +26 -12
  52. package/dist/db/createBundleDiff.cjs +2 -2
  53. package/dist/db/createBundleDiff.d.cts +1 -5
  54. package/dist/db/createBundleDiff.d.mts +1 -5
  55. package/dist/db/databasePluginCore.cjs +0 -1
  56. package/dist/db/fixedMigrator.cjs +2 -2
  57. package/dist/db/fixedMigrator.mjs +2 -2
  58. package/dist/db/fixedMigratorMongo.cjs +6 -4
  59. package/dist/db/fixedMigratorMongo.mjs +6 -4
  60. package/dist/db/index.d.cts +0 -1
  61. package/dist/db/index.d.mts +0 -1
  62. package/dist/db/releaseCatalog.cjs +0 -1
  63. package/dist/db/releaseCatalog.d.cts +0 -1
  64. package/dist/db/releaseCatalog.d.mts +0 -1
  65. package/dist/db/schema/insightsCollation.cjs +14 -0
  66. package/dist/db/schema/insightsCollation.mjs +14 -0
  67. package/dist/db/schema/sql.cjs +11 -7
  68. package/dist/db/schema/sql.mjs +8 -8
  69. package/dist/db/schemaGenerators.cjs +29 -9
  70. package/dist/db/schemaGenerators.mjs +29 -9
  71. package/dist/db/schemaReadiness.cjs +2 -0
  72. package/dist/db/schemaReadiness.d.cts +1 -0
  73. package/dist/db/schemaReadiness.d.mts +1 -0
  74. package/dist/db/schemaReadiness.mjs +2 -0
  75. package/dist/db/sqlMigrationExecution.cjs +1 -1
  76. package/dist/db/sqlMigrationExecution.mjs +1 -0
  77. package/dist/db/types.cjs +3 -1
  78. package/dist/db/types.d.cts +3 -6
  79. package/dist/db/types.d.mts +3 -6
  80. package/dist/db/types.mjs +2 -2
  81. package/dist/db/updateArtifacts.cjs +0 -1
  82. package/dist/handler.cjs +5 -5
  83. package/dist/handler.d.cts +1 -2
  84. package/dist/handler.d.mts +1 -2
  85. package/dist/handler.mjs +5 -5
  86. package/dist/handlerReleaseCatalogRoutes.cjs +0 -1
  87. package/dist/handlerReleaseManagementRoutes.cjs +0 -1
  88. package/dist/handlerTypes.d.cts +0 -1
  89. package/dist/handlerTypes.d.mts +0 -1
  90. package/dist/handlerVersionRoutes.d.cts +1 -0
  91. package/dist/handlerVersionRoutes.d.mts +1 -0
  92. package/dist/index.cjs +2 -2
  93. package/dist/index.d.cts +4 -4
  94. package/dist/index.d.mts +4 -4
  95. package/dist/index.mjs +2 -2
  96. package/dist/insights/domain.d.cts +92 -0
  97. package/dist/insights/domain.d.mts +92 -0
  98. package/dist/insights/errors.cjs +15 -0
  99. package/dist/insights/errors.mjs +14 -0
  100. package/dist/{analytics → insights}/eventInput.cjs +61 -16
  101. package/dist/{analytics → insights}/eventInput.mjs +61 -18
  102. package/dist/insights/provider.cjs +332 -0
  103. package/dist/insights/provider.d.cts +6 -0
  104. package/dist/insights/provider.d.mts +6 -0
  105. package/dist/insights/provider.mjs +332 -0
  106. package/dist/insights/queryInput.cjs +93 -0
  107. package/dist/insights/queryInput.mjs +91 -0
  108. package/dist/insights/routes.cjs +58 -0
  109. package/dist/insights/routes.mjs +56 -0
  110. package/dist/insights/types.d.cts +32 -0
  111. package/dist/insights/types.d.mts +32 -0
  112. package/dist/node.d.cts +0 -1
  113. package/dist/node.d.mts +0 -1
  114. package/dist/package.cjs +1 -1
  115. package/dist/package.mjs +1 -1
  116. package/dist/schema/index.cjs +17 -3
  117. package/dist/schema/index.mjs +4 -4
  118. package/dist/schema/v1_0_0.cjs +64 -35
  119. package/dist/schema/v1_0_0.mjs +64 -36
  120. package/dist/storageAccess.cjs +0 -1
  121. package/dist/types/index.d.cts +0 -1
  122. package/dist/types/index.d.mts +0 -1
  123. package/package.json +7 -7
  124. package/src/adapters/databasePluginTestDatabase.ts +15 -5
  125. package/src/adapters/databasePluginUtils.ts +24 -0
  126. package/src/adapters/drizzle.spec.ts +203 -5
  127. package/src/adapters/drizzle.ts +16 -4
  128. package/src/adapters/drizzleCrud.ts +200 -9
  129. package/src/adapters/drizzleLazyDB.ts +33 -6
  130. package/src/adapters/kysely.spec.ts +62 -0
  131. package/src/adapters/kysely.ts +7 -1
  132. package/src/adapters/kyselyCrud.ts +115 -7
  133. package/src/adapters/kyselyInsights.spec.ts +168 -0
  134. package/src/adapters/mongodb.integration.spec.ts +483 -0
  135. package/src/adapters/mongodb.spec.ts +89 -0
  136. package/src/adapters/mongodb.ts +59 -1
  137. package/src/adapters/mongodbCollections.ts +16 -0
  138. package/src/adapters/mongodbQuery.ts +22 -3
  139. package/src/adapters/mongodbReads.ts +78 -2
  140. package/src/adapters/mongodbTestClient.ts +107 -6
  141. package/src/adapters/mongodbTestFilter.ts +5 -1
  142. package/src/adapters/mongodbWrites.ts +1 -0
  143. package/src/adapters/prisma.spec.ts +270 -0
  144. package/src/adapters/prisma.ts +75 -2
  145. package/src/adapters/prismaInsights.ts +190 -0
  146. package/src/adapters/prismaRows.ts +17 -10
  147. package/src/adapters/prismaTestClient.ts +89 -7
  148. package/src/apiKeys.integration.spec.ts +3 -3
  149. package/src/createHotUpdaterCore.ts +30 -16
  150. package/src/db/databasePluginUpdateCheck.bench.ts +10 -0
  151. package/src/db/fixedMigrator.spec.ts +63 -0
  152. package/src/db/fixedMigratorMongo.spec.ts +70 -9
  153. package/src/db/fixedMigratorMongo.ts +10 -10
  154. package/src/db/index.spec.ts +6 -1
  155. package/src/db/schema/insightsCollation.ts +21 -0
  156. package/src/db/schema/sql.ts +8 -5
  157. package/src/db/schemaGenerators.ts +42 -13
  158. package/src/db/types.spec.ts +11 -3
  159. package/src/db/types.ts +13 -7
  160. package/src/handler-standalone.integration.spec.ts +6 -8
  161. package/src/handler.ts +12 -12
  162. package/src/index.ts +3 -3
  163. package/src/insights/domain.ts +106 -0
  164. package/src/insights/errors.ts +11 -0
  165. package/src/{analytics → insights}/eventInput.ts +66 -16
  166. package/src/insights/insights.integration.spec.ts +475 -0
  167. package/src/insights/provider.spec.ts +396 -0
  168. package/src/insights/provider.ts +611 -0
  169. package/src/insights/queryInput.ts +142 -0
  170. package/src/insights/routes.ts +104 -0
  171. package/src/insights/types.ts +55 -0
  172. package/src/schema/dsl-all-versions.spec.ts +1 -1
  173. package/src/schema/v1_0_0.spec.ts +77 -3
  174. package/src/schema/v1_0_0.ts +83 -37
  175. package/dist/analytics/bounded/activeOverview.cjs +0 -87
  176. package/dist/analytics/bounded/activeOverview.mjs +0 -85
  177. package/dist/analytics/bounded/installationSearch.cjs +0 -42
  178. package/dist/analytics/bounded/installationSearch.mjs +0 -42
  179. package/dist/analytics/bounded/persistence.cjs +0 -39
  180. package/dist/analytics/bounded/persistence.mjs +0 -38
  181. package/dist/analytics/bounded/provider.cjs +0 -170
  182. package/dist/analytics/bounded/provider.d.cts +0 -7
  183. package/dist/analytics/bounded/provider.d.mts +0 -7
  184. package/dist/analytics/bounded/provider.mjs +0 -170
  185. package/dist/analytics/bounded/scan.cjs +0 -144
  186. package/dist/analytics/bounded/scan.mjs +0 -138
  187. package/dist/analytics/domain.d.cts +0 -121
  188. package/dist/analytics/domain.d.mts +0 -121
  189. package/dist/analytics/errors.cjs +0 -22
  190. package/dist/analytics/errors.mjs +0 -20
  191. package/dist/analytics/persistence.d.cts +0 -6
  192. package/dist/analytics/persistence.d.mts +0 -6
  193. package/dist/analytics/queryInput.cjs +0 -58
  194. package/dist/analytics/queryInput.mjs +0 -55
  195. package/dist/analytics/routes.cjs +0 -63
  196. package/dist/analytics/routes.mjs +0 -61
  197. package/dist/analytics/types.d.cts +0 -17
  198. package/dist/analytics/types.d.mts +0 -17
  199. package/src/analytics/analytics.integration.spec.ts +0 -144
  200. package/src/analytics/bounded/activeOverview.spec.ts +0 -189
  201. package/src/analytics/bounded/activeOverview.ts +0 -148
  202. package/src/analytics/bounded/installationSearch.spec.ts +0 -130
  203. package/src/analytics/bounded/installationSearch.ts +0 -69
  204. package/src/analytics/bounded/persistence.ts +0 -43
  205. package/src/analytics/bounded/provider.spec.ts +0 -219
  206. package/src/analytics/bounded/provider.ts +0 -229
  207. package/src/analytics/bounded/scan.ts +0 -235
  208. package/src/analytics/domain.ts +0 -139
  209. package/src/analytics/errors.ts +0 -18
  210. package/src/analytics/persistence.ts +0 -10
  211. package/src/analytics/queryInput.ts +0 -102
  212. package/src/analytics/routes.ts +0 -123
  213. package/src/analytics/types.ts +0 -44
@@ -0,0 +1,99 @@
1
+ const require_prismaRows = require("./prismaRows.cjs");
2
+ let _hot_updater_plugin_core_internal = require("@hot-updater/plugin-core/internal");
3
+ //#region src/adapters/prismaInsights.ts
4
+ const headFields = [
5
+ "install_id",
6
+ "id",
7
+ "received_at_ms",
8
+ "user_id",
9
+ "platform",
10
+ "channel",
11
+ "type",
12
+ "from_bundle_id",
13
+ "to_bundle_id"
14
+ ];
15
+ const parameter = (provider, index, field) => {
16
+ if (provider !== "postgresql" && provider !== "cockroachdb") return "?";
17
+ return `$${index}${field === "metadata" ? "::jsonb" : [
18
+ "id",
19
+ "from_release_id",
20
+ "from_bundle_id",
21
+ "to_release_id",
22
+ "to_bundle_id"
23
+ ].includes(field ?? "") ? "::uuid" : ""}`;
24
+ };
25
+ const headConflict = (provider) => {
26
+ const newer = "(excluded.received_at_ms > bundle_event_heads.received_at_ms OR (excluded.received_at_ms = bundle_event_heads.received_at_ms AND excluded.id > bundle_event_heads.id))";
27
+ if (provider === "mysql") {
28
+ const mysqlNewer = newer.replace(/excluded\.(\w+)/g, "VALUES($1)");
29
+ return `ON DUPLICATE KEY UPDATE ${[
30
+ ...headFields.filter((field) => ![
31
+ "install_id",
32
+ "id",
33
+ "received_at_ms"
34
+ ].includes(field)),
35
+ "id",
36
+ "received_at_ms"
37
+ ].map((field) => `${field} = IF(${mysqlNewer}, VALUES(${field}), bundle_event_heads.${field})`).join(", ")}`;
38
+ }
39
+ return `ON CONFLICT (install_id) DO UPDATE SET ${headFields.filter((field) => field !== "install_id").map((field) => `${field} = excluded.${field}`).join(", ")} WHERE ${newer}`;
40
+ };
41
+ const executePrismaInsights = async (client, query, values) => {
42
+ if (!("$executeRawUnsafe" in client) || typeof client.$executeRawUnsafe !== "function") throw new require_prismaRows.PrismaAdapterError("Insights writes require native SQL support");
43
+ await client.$executeRawUnsafe(query, ...values);
44
+ };
45
+ const updatePrismaEventHead = (client, provider, event) => executePrismaInsights(client, `INSERT INTO bundle_event_heads (${headFields.join(", ")}) VALUES (${headFields.map((field, index) => parameter(provider, index + 1, field)).join(", ")}) ${headConflict(provider)}`, headFields.map((field) => event[field]));
46
+ /** PostgreSQL clients without callback transactions can publish both rows atomically. */
47
+ const recordPrismaEventWithCte = (client, provider, event) => {
48
+ if (provider !== "postgresql" && provider !== "cockroachdb") throw new require_prismaRows.PrismaAdapterError("Insights writes require callback transactions");
49
+ const fields = [
50
+ "id",
51
+ "type",
52
+ "install_id",
53
+ "user_id",
54
+ "from_release_id",
55
+ "from_bundle_id",
56
+ "to_release_id",
57
+ "to_bundle_id",
58
+ "platform",
59
+ "app_version",
60
+ "channel",
61
+ "metadata",
62
+ "received_at_ms"
63
+ ];
64
+ return executePrismaInsights(client, `WITH inserted AS (INSERT INTO bundle_events (${fields.join(", ")}) VALUES (${fields.map((field, index) => parameter(provider, index + 1, field)).join(", ")}) ON CONFLICT (id) DO NOTHING RETURNING ${headFields.join(", ")}) INSERT INTO bundle_event_heads (${headFields.join(", ")}) SELECT ${headFields.join(", ")} FROM inserted ${headConflict(provider)}`, fields.map((field) => field === "metadata" ? JSON.stringify(event[field]) : event[field]));
65
+ };
66
+ const queryPrismaLatestEvents = async (client, provider, input) => {
67
+ if (!("$queryRawUnsafe" in client) || typeof client.$queryRawUnsafe !== "function") throw new require_prismaRows.PrismaAdapterError("Insights reads require native SQL query support");
68
+ const values = [];
69
+ const bind = (value, field) => {
70
+ values.push(value);
71
+ return parameter(provider, values.length, field);
72
+ };
73
+ const groups = "sinceMs" in input ? (0, _hot_updater_plugin_core_internal.latestInsightsCountGroups)(input) : [(0, _hot_updater_plugin_core_internal.latestInsightsWhere)(input)];
74
+ let firstGroupValues = [];
75
+ const predicates = groups.map((group, index) => {
76
+ const predicate = `(${group.map((where) => where.operator === "in" && Array.isArray(where.value) ? `${where.field} IN (${where.value.map((value) => bind(value, where.field)).join(", ")})` : `${where.field} ${where.operator === "gte" ? ">=" : where.operator === "gt" ? ">" : "="} ${bind(where.value, where.field)}`).join(" AND ")})`;
77
+ if (index === 0) firstGroupValues = values.slice();
78
+ return predicate;
79
+ });
80
+ const counting = "sinceMs" in input;
81
+ const page = counting ? "" : ` ORDER BY install_id ASC LIMIT ${bind("installId" in input ? 1 : input.limit)}`;
82
+ let selection = `SELECT ${counting ? "COUNT(*) AS count" : "id, install_id"} FROM bundle_event_heads WHERE (${predicates.join(" OR ")})${page}`;
83
+ if (counting && provider === "mysql" && predicates.length === 2) {
84
+ selection = `SELECT (SELECT COUNT(*) FROM bundle_event_heads WHERE ${predicates[0]}) + (SELECT COUNT(*) FROM bundle_event_heads WHERE ${predicates[1]} AND ${predicates[0]} IS NOT TRUE) AS count`;
85
+ values.push(...firstGroupValues);
86
+ }
87
+ const rows = await client.$queryRawUnsafe(counting ? selection : `SELECT event.* FROM (${selection}) AS head JOIN bundle_events AS event ON event.id = head.id ORDER BY head.install_id ASC`, ...values);
88
+ if (!Array.isArray(rows)) throw new require_prismaRows.PrismaAdapterError("invalid latest-event query result");
89
+ if (counting) {
90
+ const count = rows[0]?.count;
91
+ if (typeof count !== "number" && typeof count !== "bigint") throw new require_prismaRows.PrismaAdapterError("invalid latest-event count");
92
+ return Number(count);
93
+ }
94
+ return rows.map(require_prismaRows.parsePrismaBundleEventRow);
95
+ };
96
+ //#endregion
97
+ exports.queryPrismaLatestEvents = queryPrismaLatestEvents;
98
+ exports.recordPrismaEventWithCte = recordPrismaEventWithCte;
99
+ exports.updatePrismaEventHead = updatePrismaEventHead;
@@ -0,0 +1,97 @@
1
+ import { PrismaAdapterError, parsePrismaBundleEventRow } from "./prismaRows.mjs";
2
+ import { latestInsightsCountGroups, latestInsightsWhere } from "@hot-updater/plugin-core/internal";
3
+ //#region src/adapters/prismaInsights.ts
4
+ const headFields = [
5
+ "install_id",
6
+ "id",
7
+ "received_at_ms",
8
+ "user_id",
9
+ "platform",
10
+ "channel",
11
+ "type",
12
+ "from_bundle_id",
13
+ "to_bundle_id"
14
+ ];
15
+ const parameter = (provider, index, field) => {
16
+ if (provider !== "postgresql" && provider !== "cockroachdb") return "?";
17
+ return `$${index}${field === "metadata" ? "::jsonb" : [
18
+ "id",
19
+ "from_release_id",
20
+ "from_bundle_id",
21
+ "to_release_id",
22
+ "to_bundle_id"
23
+ ].includes(field ?? "") ? "::uuid" : ""}`;
24
+ };
25
+ const headConflict = (provider) => {
26
+ const newer = "(excluded.received_at_ms > bundle_event_heads.received_at_ms OR (excluded.received_at_ms = bundle_event_heads.received_at_ms AND excluded.id > bundle_event_heads.id))";
27
+ if (provider === "mysql") {
28
+ const mysqlNewer = newer.replace(/excluded\.(\w+)/g, "VALUES($1)");
29
+ return `ON DUPLICATE KEY UPDATE ${[
30
+ ...headFields.filter((field) => ![
31
+ "install_id",
32
+ "id",
33
+ "received_at_ms"
34
+ ].includes(field)),
35
+ "id",
36
+ "received_at_ms"
37
+ ].map((field) => `${field} = IF(${mysqlNewer}, VALUES(${field}), bundle_event_heads.${field})`).join(", ")}`;
38
+ }
39
+ return `ON CONFLICT (install_id) DO UPDATE SET ${headFields.filter((field) => field !== "install_id").map((field) => `${field} = excluded.${field}`).join(", ")} WHERE ${newer}`;
40
+ };
41
+ const executePrismaInsights = async (client, query, values) => {
42
+ if (!("$executeRawUnsafe" in client) || typeof client.$executeRawUnsafe !== "function") throw new PrismaAdapterError("Insights writes require native SQL support");
43
+ await client.$executeRawUnsafe(query, ...values);
44
+ };
45
+ const updatePrismaEventHead = (client, provider, event) => executePrismaInsights(client, `INSERT INTO bundle_event_heads (${headFields.join(", ")}) VALUES (${headFields.map((field, index) => parameter(provider, index + 1, field)).join(", ")}) ${headConflict(provider)}`, headFields.map((field) => event[field]));
46
+ /** PostgreSQL clients without callback transactions can publish both rows atomically. */
47
+ const recordPrismaEventWithCte = (client, provider, event) => {
48
+ if (provider !== "postgresql" && provider !== "cockroachdb") throw new PrismaAdapterError("Insights writes require callback transactions");
49
+ const fields = [
50
+ "id",
51
+ "type",
52
+ "install_id",
53
+ "user_id",
54
+ "from_release_id",
55
+ "from_bundle_id",
56
+ "to_release_id",
57
+ "to_bundle_id",
58
+ "platform",
59
+ "app_version",
60
+ "channel",
61
+ "metadata",
62
+ "received_at_ms"
63
+ ];
64
+ return executePrismaInsights(client, `WITH inserted AS (INSERT INTO bundle_events (${fields.join(", ")}) VALUES (${fields.map((field, index) => parameter(provider, index + 1, field)).join(", ")}) ON CONFLICT (id) DO NOTHING RETURNING ${headFields.join(", ")}) INSERT INTO bundle_event_heads (${headFields.join(", ")}) SELECT ${headFields.join(", ")} FROM inserted ${headConflict(provider)}`, fields.map((field) => field === "metadata" ? JSON.stringify(event[field]) : event[field]));
65
+ };
66
+ const queryPrismaLatestEvents = async (client, provider, input) => {
67
+ if (!("$queryRawUnsafe" in client) || typeof client.$queryRawUnsafe !== "function") throw new PrismaAdapterError("Insights reads require native SQL query support");
68
+ const values = [];
69
+ const bind = (value, field) => {
70
+ values.push(value);
71
+ return parameter(provider, values.length, field);
72
+ };
73
+ const groups = "sinceMs" in input ? latestInsightsCountGroups(input) : [latestInsightsWhere(input)];
74
+ let firstGroupValues = [];
75
+ const predicates = groups.map((group, index) => {
76
+ const predicate = `(${group.map((where) => where.operator === "in" && Array.isArray(where.value) ? `${where.field} IN (${where.value.map((value) => bind(value, where.field)).join(", ")})` : `${where.field} ${where.operator === "gte" ? ">=" : where.operator === "gt" ? ">" : "="} ${bind(where.value, where.field)}`).join(" AND ")})`;
77
+ if (index === 0) firstGroupValues = values.slice();
78
+ return predicate;
79
+ });
80
+ const counting = "sinceMs" in input;
81
+ const page = counting ? "" : ` ORDER BY install_id ASC LIMIT ${bind("installId" in input ? 1 : input.limit)}`;
82
+ let selection = `SELECT ${counting ? "COUNT(*) AS count" : "id, install_id"} FROM bundle_event_heads WHERE (${predicates.join(" OR ")})${page}`;
83
+ if (counting && provider === "mysql" && predicates.length === 2) {
84
+ selection = `SELECT (SELECT COUNT(*) FROM bundle_event_heads WHERE ${predicates[0]}) + (SELECT COUNT(*) FROM bundle_event_heads WHERE ${predicates[1]} AND ${predicates[0]} IS NOT TRUE) AS count`;
85
+ values.push(...firstGroupValues);
86
+ }
87
+ const rows = await client.$queryRawUnsafe(counting ? selection : `SELECT event.* FROM (${selection}) AS head JOIN bundle_events AS event ON event.id = head.id ORDER BY head.install_id ASC`, ...values);
88
+ if (!Array.isArray(rows)) throw new PrismaAdapterError("invalid latest-event query result");
89
+ if (counting) {
90
+ const count = rows[0]?.count;
91
+ if (typeof count !== "number" && typeof count !== "bigint") throw new PrismaAdapterError("invalid latest-event count");
92
+ return Number(count);
93
+ }
94
+ return rows.map(parsePrismaBundleEventRow);
95
+ };
96
+ //#endregion
97
+ export { queryPrismaLatestEvents, recordPrismaEventWithCte, updatePrismaEventHead };
@@ -1,4 +1,3 @@
1
- require("../_virtual/_rolldown/runtime.cjs");
2
1
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
3
2
  //#region src/adapters/prismaQuery.ts
4
3
  const stringFilter = (operator, value, mode) => {
@@ -1,7 +1,7 @@
1
- require("../_virtual/_rolldown/runtime.cjs");
2
1
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
3
2
  //#region src/adapters/prismaRows.ts
4
3
  var PrismaAdapterError = class extends Error {
4
+ reason;
5
5
  name = "PrismaAdapterError";
6
6
  constructor(reason) {
7
7
  super(`Invalid Prisma plugin state: ${reason}`);
@@ -92,14 +92,16 @@ const parsePrismaBundleEventRow = (value) => {
92
92
  const type = readString(value, "type");
93
93
  const platform = readString(value, "platform");
94
94
  const fromBundleId = readNullableString(value, "from_bundle_id");
95
- const updateStrategy = readNullableString(value, "update_strategy");
96
- if (platform !== "ios" && platform !== "android" || !((type === "UPDATE_APPLIED" || type === "RECOVERED" || type === "RELEASE_ADOPTED") && typeof fromBundleId === "string" && (updateStrategy === "fingerprint" || updateStrategy === "appVersion") || type === "UNCHANGED" && fromBundleId === null && updateStrategy === null)) throw new PrismaAdapterError("invalid event shape");
95
+ const storedMetadata = value["metadata"];
96
+ const metadata = typeof storedMetadata === "string" ? JSON.parse(storedMetadata) : storedMetadata;
97
+ if (!(0, _hot_updater_plugin_core.isDatabaseBundleEventMetadata)(metadata)) throw new PrismaAdapterError("invalid event metadata");
98
+ const updateStrategy = metadata.update_strategy;
99
+ if (platform !== "ios" && platform !== "android" || !((type === "UPDATE_DOWNLOADED" || type === "UPDATE_APPLIED" || type === "RECOVERED") && typeof fromBundleId === "string" && (updateStrategy === "fingerprint" || updateStrategy === "appVersion") || type === "UNCHANGED" && fromBundleId === null && updateStrategy === null)) throw new PrismaAdapterError("invalid event shape");
97
100
  return {
98
101
  id: readString(value, "id"),
99
102
  type,
100
103
  install_id: readString(value, "install_id"),
101
104
  user_id: readNullableString(value, "user_id"),
102
- username: readNullableString(value, "username"),
103
105
  from_release_id: readNullableString(value, "from_release_id"),
104
106
  from_bundle_id: fromBundleId,
105
107
  to_release_id: readNullableString(value, "to_release_id"),
@@ -107,10 +109,7 @@ const parsePrismaBundleEventRow = (value) => {
107
109
  platform,
108
110
  app_version: readString(value, "app_version"),
109
111
  channel: readString(value, "channel"),
110
- cohort: readString(value, "cohort"),
111
- update_strategy: updateStrategy,
112
- fingerprint_hash: readNullableString(value, "fingerprint_hash"),
113
- sdk_version: readNullableString(value, "sdk_version"),
112
+ metadata,
114
113
  received_at_ms: readNumber(value, "received_at_ms")
115
114
  };
116
115
  };
@@ -1,6 +1,7 @@
1
- import { isDatabaseMetadataObject } from "@hot-updater/plugin-core";
1
+ import { isDatabaseBundleEventMetadata, isDatabaseMetadataObject } from "@hot-updater/plugin-core";
2
2
  //#region src/adapters/prismaRows.ts
3
3
  var PrismaAdapterError = class extends Error {
4
+ reason;
4
5
  name = "PrismaAdapterError";
5
6
  constructor(reason) {
6
7
  super(`Invalid Prisma plugin state: ${reason}`);
@@ -91,14 +92,16 @@ const parsePrismaBundleEventRow = (value) => {
91
92
  const type = readString(value, "type");
92
93
  const platform = readString(value, "platform");
93
94
  const fromBundleId = readNullableString(value, "from_bundle_id");
94
- const updateStrategy = readNullableString(value, "update_strategy");
95
- if (platform !== "ios" && platform !== "android" || !((type === "UPDATE_APPLIED" || type === "RECOVERED" || type === "RELEASE_ADOPTED") && typeof fromBundleId === "string" && (updateStrategy === "fingerprint" || updateStrategy === "appVersion") || type === "UNCHANGED" && fromBundleId === null && updateStrategy === null)) throw new PrismaAdapterError("invalid event shape");
95
+ const storedMetadata = value["metadata"];
96
+ const metadata = typeof storedMetadata === "string" ? JSON.parse(storedMetadata) : storedMetadata;
97
+ if (!isDatabaseBundleEventMetadata(metadata)) throw new PrismaAdapterError("invalid event metadata");
98
+ const updateStrategy = metadata.update_strategy;
99
+ if (platform !== "ios" && platform !== "android" || !((type === "UPDATE_DOWNLOADED" || type === "UPDATE_APPLIED" || type === "RECOVERED") && typeof fromBundleId === "string" && (updateStrategy === "fingerprint" || updateStrategy === "appVersion") || type === "UNCHANGED" && fromBundleId === null && updateStrategy === null)) throw new PrismaAdapterError("invalid event shape");
96
100
  return {
97
101
  id: readString(value, "id"),
98
102
  type,
99
103
  install_id: readString(value, "install_id"),
100
104
  user_id: readNullableString(value, "user_id"),
101
- username: readNullableString(value, "username"),
102
105
  from_release_id: readNullableString(value, "from_release_id"),
103
106
  from_bundle_id: fromBundleId,
104
107
  to_release_id: readNullableString(value, "to_release_id"),
@@ -106,10 +109,7 @@ const parsePrismaBundleEventRow = (value) => {
106
109
  platform,
107
110
  app_version: readString(value, "app_version"),
108
111
  channel: readString(value, "channel"),
109
- cohort: readString(value, "cohort"),
110
- update_strategy: updateStrategy,
111
- fingerprint_hash: readNullableString(value, "fingerprint_hash"),
112
- sdk_version: readNullableString(value, "sdk_version"),
112
+ metadata,
113
113
  received_at_ms: readNumber(value, "received_at_ms")
114
114
  };
115
115
  };
package/dist/apiKeys.cjs CHANGED
@@ -33,7 +33,7 @@ const hashApiKey = async (apiKey) => {
33
33
  return bytesToBase64Url(new Uint8Array(digest));
34
34
  };
35
35
  const apiKeyId = () => {
36
- const bytes = new Uint8Array(16);
36
+ const bytes = /* @__PURE__ */ new Uint8Array(16);
37
37
  crypto.getRandomValues(bytes);
38
38
  return `api-${bytesToBase64Url(bytes)}`;
39
39
  };
@@ -70,7 +70,7 @@ const registerApiKey = async (input) => {
70
70
  });
71
71
  };
72
72
  const createApiKey = (input) => {
73
- const bytes = new Uint8Array(32);
73
+ const bytes = /* @__PURE__ */ new Uint8Array(32);
74
74
  crypto.getRandomValues(bytes);
75
75
  return registerApiKey({
76
76
  apiKey: bytesToBase64Url(bytes),
@@ -131,9 +131,13 @@ const createApiKeyManagement = (input) => Object.freeze({
131
131
  });
132
132
  //#endregion
133
133
  exports.API_KEY_HEADER_NAME = API_KEY_HEADER_NAME;
134
+ exports.apiKeyId = apiKeyId;
134
135
  exports.authenticateApiKey = authenticateApiKey;
135
136
  exports.createApiKey = createApiKey;
136
137
  exports.createApiKeyManagement = createApiKeyManagement;
138
+ exports.hashApiKey = hashApiKey;
139
+ exports.isApiKey = isApiKey;
137
140
  exports.normalizeApiKeyHeaderName = normalizeApiKeyHeaderName;
141
+ exports.normalizeApiKeyName = normalizeApiKeyName;
138
142
  exports.provisionApiKey = provisionApiKey;
139
143
  exports.registerApiKey = registerApiKey;
@@ -1,5 +1,4 @@
1
1
  import { ApiKeyModel, ApiKeyRow } from "@hot-updater/plugin-core";
2
-
3
2
  //#region src/apiKeys.d.ts
4
3
  declare const API_KEY_HEADER_NAME = "x-api-key";
5
4
  type ApiKeyMetadata = Omit<ApiKeyRow, "hash">;
@@ -1,5 +1,4 @@
1
1
  import { ApiKeyModel, ApiKeyRow } from "@hot-updater/plugin-core";
2
-
3
2
  //#region src/apiKeys.d.ts
4
3
  declare const API_KEY_HEADER_NAME = "x-api-key";
5
4
  type ApiKeyMetadata = Omit<ApiKeyRow, "hash">;
package/dist/apiKeys.mjs CHANGED
@@ -33,7 +33,7 @@ const hashApiKey = async (apiKey) => {
33
33
  return bytesToBase64Url(new Uint8Array(digest));
34
34
  };
35
35
  const apiKeyId = () => {
36
- const bytes = new Uint8Array(16);
36
+ const bytes = /* @__PURE__ */ new Uint8Array(16);
37
37
  crypto.getRandomValues(bytes);
38
38
  return `api-${bytesToBase64Url(bytes)}`;
39
39
  };
@@ -70,7 +70,7 @@ const registerApiKey = async (input) => {
70
70
  });
71
71
  };
72
72
  const createApiKey = (input) => {
73
- const bytes = new Uint8Array(32);
73
+ const bytes = /* @__PURE__ */ new Uint8Array(32);
74
74
  crypto.getRandomValues(bytes);
75
75
  return registerApiKey({
76
76
  apiKey: bytesToBase64Url(bytes),
@@ -130,4 +130,4 @@ const createApiKeyManagement = (input) => Object.freeze({
130
130
  }
131
131
  });
132
132
  //#endregion
133
- export { API_KEY_HEADER_NAME, authenticateApiKey, createApiKey, createApiKeyManagement, normalizeApiKeyHeaderName, provisionApiKey, registerApiKey };
133
+ export { API_KEY_HEADER_NAME, apiKeyId, authenticateApiKey, createApiKey, createApiKeyManagement, hashApiKey, isApiKey, normalizeApiKeyHeaderName, normalizeApiKeyName, provisionApiKey, registerApiKey };
@@ -1,6 +1,5 @@
1
- require("./_virtual/_rolldown/runtime.cjs");
2
1
  const require_handler = require("./handler.cjs");
3
- const require_provider = require("./analytics/bounded/provider.cjs");
2
+ const require_provider = require("./insights/provider.cjs");
4
3
  const require_apiKeys = require("./apiKeys.cjs");
5
4
  const require_databasePluginCore = require("./db/databasePluginCore.cjs");
6
5
  const require_schemaReadiness = require("./db/schemaReadiness.cjs");
@@ -25,34 +24,48 @@ function getHotUpdaterCoreMetadata(hotUpdater) {
25
24
  function createHotUpdaterCore(options) {
26
25
  for (const key of ["authorityId", "catalogId"]) if (Object.hasOwn(options, key)) throw new TypeError(`Remove ${key} from createHotUpdater options. Catalog identity is managed internally.`);
27
26
  const database = options.database;
28
- const { downloadStorageObject, readStorageText, resolveFileUrl } = require_storageAccess.createStorageAccess((options.storage ?? []).map((storage) => {
27
+ const storagePlugins = (options.storage ?? []).map((storage) => {
29
28
  (0, _hot_updater_plugin_core.assertStorageOperations)(storage, ["get", "getDownloadUrl"]);
30
29
  return storage;
31
- }));
30
+ });
31
+ const { downloadStorageObject, readStorageText, resolveFileUrl } = require_storageAccess.createStorageAccess(storagePlugins);
32
32
  const adapterCapabilities = database;
33
33
  if (!require_types.isDatabasePlugin(database)) throw new Error("@hot-updater/server only supports database plugins.");
34
34
  const plugin = database;
35
- const assertSchemaReady = require_schemaReadiness.createSchemaReadinessChecker(adapterCapabilities.adapterName ?? plugin.name, adapterCapabilities.createMigrator);
35
+ const adapterName = adapterCapabilities.adapterName ?? plugin.name;
36
+ const assertSchemaReady = require_schemaReadiness.createSchemaReadinessChecker(adapterName, adapterCapabilities.createMigrator);
36
37
  const core = require_databasePluginCore.createDatabasePluginCore(plugin, resolveFileUrl, {
37
38
  beforeOperation: assertSchemaReady,
38
39
  readStorageText
39
40
  });
40
41
  const clientAccess = normalizeClientAccess(options.clientAccess);
41
- const analytics = require_provider.createAnalyticsProvider({
42
- async append(row) {
42
+ const insights = require_provider.createInsightsProvider({
43
+ async recordEvent(input) {
44
+ await assertSchemaReady();
45
+ return plugin.models.insights.recordEvent(input);
46
+ },
47
+ async listEvents(input) {
48
+ await assertSchemaReady();
49
+ return plugin.models.insights.listEvents(input);
50
+ },
51
+ async findLatestEvents(input) {
52
+ await assertSchemaReady();
53
+ return plugin.models.insights.findLatestEvents(input);
54
+ },
55
+ async countLatestEvents(input) {
43
56
  await assertSchemaReady();
44
- return plugin.models.analytics.append(row);
57
+ return plugin.models.insights.countLatestEvents(input);
45
58
  },
46
- async scan(input) {
59
+ async countEvents(input) {
47
60
  await assertSchemaReady();
48
- return plugin.models.analytics.scan(input);
61
+ return plugin.models.insights.countEvents(input);
49
62
  }
50
63
  });
51
64
  const apiKeys = require_apiKeys.createApiKeyManagement({
52
65
  apiKeys: plugin.models.apiKeys,
53
66
  beforeOperation: assertSchemaReady
54
67
  });
55
- const handlers = require_handler.createHotUpdaterHandlers(core.api, analytics, clientAccess.type === "api-key" ? {
68
+ const handlers = require_handler.createHotUpdaterHandlers(core.api, insights, clientAccess.type === "api-key" ? {
56
69
  authenticate: (request) => require_apiKeys.authenticateApiKey({
57
70
  apiKeys: plugin.models.apiKeys,
58
71
  beforeLookup: assertSchemaReady,
@@ -63,7 +76,7 @@ function createHotUpdaterCore(options) {
63
76
  } : void 0, downloadStorageObject);
64
77
  const api = Object.assign({
65
78
  adapterName: adapterCapabilities.adapterName ?? core.adapterName,
66
- analytics,
79
+ insights,
67
80
  apiKeys,
68
81
  handlers
69
82
  }, core.api);
@@ -85,4 +98,6 @@ function createHotUpdater(options) {
85
98
  }
86
99
  //#endregion
87
100
  exports.createHotUpdater = createHotUpdater;
101
+ exports.createHotUpdaterCore = createHotUpdaterCore;
88
102
  exports.getHotUpdaterCoreMetadata = getHotUpdaterCoreMetadata;
103
+ exports.hotUpdaterCoreMetadata = hotUpdaterCoreMetadata;
@@ -1,19 +1,19 @@
1
- import { AnalyticsProvider } from "./analytics/types.cjs";
2
1
  import { ApiKeyManagementAPI } from "./apiKeys.cjs";
3
2
  import { HotUpdaterHandlers } from "./handlerTypes.cjs";
3
+ import { InsightsProvider } from "./insights/types.cjs";
4
+ import "./handler.cjs";
4
5
  import { DatabaseAPI, DatabasePlugin as DatabasePlugin$1 } from "./db/types.cjs";
5
6
  import { StoragePlugin } from "@hot-updater/plugin-core";
6
-
7
7
  //#region src/createHotUpdaterCore.d.ts
8
8
  type RuntimeHotUpdaterAPI = DatabaseAPI & {
9
9
  readonly handlers: HotUpdaterHandlers;
10
10
  readonly adapterName: string;
11
11
  /**
12
- * Built-in Analytics provider. Client ingestion and admin query routes are
13
- * always mounted; React Native clients independently opt into lifecycle
14
- * reporting with `HotUpdater.init({ analytics: true })`.
12
+ * Built-in Insights provider. Client ingestion and admin query routes are
13
+ * always mounted; React Native clients report lifecycle events by default
14
+ * and can opt out with `HotUpdater.init({ insights: false })`.
15
15
  */
16
- readonly analytics: AnalyticsProvider;
16
+ readonly insights: InsightsProvider;
17
17
  /**
18
18
  * In-process API key lifecycle operations for trusted server tooling.
19
19
  * Creation returns the plaintext once; list and revoke expose only metadata.
@@ -24,14 +24,14 @@ type RuntimeHotUpdaterAPI = DatabaseAPI & {
24
24
  type HotUpdaterAPI = RuntimeHotUpdaterAPI;
25
25
  type ClientAccessPolicy = {
26
26
  /**
27
- * Leaves Release Catalog, artifact, and Analytics ingestion routes
27
+ * Leaves Release Catalog, artifact, and Insights ingestion routes
28
28
  * publicly accessible without a client credential.
29
29
  */
30
30
  readonly type: "public";
31
31
  } | {
32
32
  /**
33
33
  * Requires a key registered in `database.models.apiKeys` for
34
- * Release Catalog, artifact, and Analytics ingestion requests.
34
+ * Release Catalog, artifact, and Insights ingestion requests.
35
35
  */
36
36
  readonly type: "api-key";
37
37
  /**
@@ -1,19 +1,19 @@
1
- import { AnalyticsProvider } from "./analytics/types.mjs";
2
1
  import { ApiKeyManagementAPI } from "./apiKeys.mjs";
3
2
  import { HotUpdaterHandlers } from "./handlerTypes.mjs";
3
+ import { InsightsProvider } from "./insights/types.mjs";
4
+ import "./handler.mjs";
4
5
  import { DatabaseAPI, DatabasePlugin as DatabasePlugin$1 } from "./db/types.mjs";
5
6
  import { StoragePlugin } from "@hot-updater/plugin-core";
6
-
7
7
  //#region src/createHotUpdaterCore.d.ts
8
8
  type RuntimeHotUpdaterAPI = DatabaseAPI & {
9
9
  readonly handlers: HotUpdaterHandlers;
10
10
  readonly adapterName: string;
11
11
  /**
12
- * Built-in Analytics provider. Client ingestion and admin query routes are
13
- * always mounted; React Native clients independently opt into lifecycle
14
- * reporting with `HotUpdater.init({ analytics: true })`.
12
+ * Built-in Insights provider. Client ingestion and admin query routes are
13
+ * always mounted; React Native clients report lifecycle events by default
14
+ * and can opt out with `HotUpdater.init({ insights: false })`.
15
15
  */
16
- readonly analytics: AnalyticsProvider;
16
+ readonly insights: InsightsProvider;
17
17
  /**
18
18
  * In-process API key lifecycle operations for trusted server tooling.
19
19
  * Creation returns the plaintext once; list and revoke expose only metadata.
@@ -24,14 +24,14 @@ type RuntimeHotUpdaterAPI = DatabaseAPI & {
24
24
  type HotUpdaterAPI = RuntimeHotUpdaterAPI;
25
25
  type ClientAccessPolicy = {
26
26
  /**
27
- * Leaves Release Catalog, artifact, and Analytics ingestion routes
27
+ * Leaves Release Catalog, artifact, and Insights ingestion routes
28
28
  * publicly accessible without a client credential.
29
29
  */
30
30
  readonly type: "public";
31
31
  } | {
32
32
  /**
33
33
  * Requires a key registered in `database.models.apiKeys` for
34
- * Release Catalog, artifact, and Analytics ingestion requests.
34
+ * Release Catalog, artifact, and Insights ingestion requests.
35
35
  */
36
36
  readonly type: "api-key";
37
37
  /**
@@ -1,5 +1,5 @@
1
1
  import { createHotUpdaterHandlers } from "./handler.mjs";
2
- import { createAnalyticsProvider } from "./analytics/bounded/provider.mjs";
2
+ import { createInsightsProvider } from "./insights/provider.mjs";
3
3
  import { authenticateApiKey, createApiKeyManagement, normalizeApiKeyHeaderName } from "./apiKeys.mjs";
4
4
  import { createDatabasePluginCore } from "./db/databasePluginCore.mjs";
5
5
  import { createSchemaReadinessChecker } from "./db/schemaReadiness.mjs";
@@ -24,34 +24,48 @@ function getHotUpdaterCoreMetadata(hotUpdater) {
24
24
  function createHotUpdaterCore(options) {
25
25
  for (const key of ["authorityId", "catalogId"]) if (Object.hasOwn(options, key)) throw new TypeError(`Remove ${key} from createHotUpdater options. Catalog identity is managed internally.`);
26
26
  const database = options.database;
27
- const { downloadStorageObject, readStorageText, resolveFileUrl } = createStorageAccess((options.storage ?? []).map((storage) => {
27
+ const storagePlugins = (options.storage ?? []).map((storage) => {
28
28
  assertStorageOperations(storage, ["get", "getDownloadUrl"]);
29
29
  return storage;
30
- }));
30
+ });
31
+ const { downloadStorageObject, readStorageText, resolveFileUrl } = createStorageAccess(storagePlugins);
31
32
  const adapterCapabilities = database;
32
33
  if (!isDatabasePlugin(database)) throw new Error("@hot-updater/server only supports database plugins.");
33
34
  const plugin = database;
34
- const assertSchemaReady = createSchemaReadinessChecker(adapterCapabilities.adapterName ?? plugin.name, adapterCapabilities.createMigrator);
35
+ const adapterName = adapterCapabilities.adapterName ?? plugin.name;
36
+ const assertSchemaReady = createSchemaReadinessChecker(adapterName, adapterCapabilities.createMigrator);
35
37
  const core = createDatabasePluginCore(plugin, resolveFileUrl, {
36
38
  beforeOperation: assertSchemaReady,
37
39
  readStorageText
38
40
  });
39
41
  const clientAccess = normalizeClientAccess(options.clientAccess);
40
- const analytics = createAnalyticsProvider({
41
- async append(row) {
42
+ const insights = createInsightsProvider({
43
+ async recordEvent(input) {
44
+ await assertSchemaReady();
45
+ return plugin.models.insights.recordEvent(input);
46
+ },
47
+ async listEvents(input) {
48
+ await assertSchemaReady();
49
+ return plugin.models.insights.listEvents(input);
50
+ },
51
+ async findLatestEvents(input) {
52
+ await assertSchemaReady();
53
+ return plugin.models.insights.findLatestEvents(input);
54
+ },
55
+ async countLatestEvents(input) {
42
56
  await assertSchemaReady();
43
- return plugin.models.analytics.append(row);
57
+ return plugin.models.insights.countLatestEvents(input);
44
58
  },
45
- async scan(input) {
59
+ async countEvents(input) {
46
60
  await assertSchemaReady();
47
- return plugin.models.analytics.scan(input);
61
+ return plugin.models.insights.countEvents(input);
48
62
  }
49
63
  });
50
64
  const apiKeys = createApiKeyManagement({
51
65
  apiKeys: plugin.models.apiKeys,
52
66
  beforeOperation: assertSchemaReady
53
67
  });
54
- const handlers = createHotUpdaterHandlers(core.api, analytics, clientAccess.type === "api-key" ? {
68
+ const handlers = createHotUpdaterHandlers(core.api, insights, clientAccess.type === "api-key" ? {
55
69
  authenticate: (request) => authenticateApiKey({
56
70
  apiKeys: plugin.models.apiKeys,
57
71
  beforeLookup: assertSchemaReady,
@@ -62,7 +76,7 @@ function createHotUpdaterCore(options) {
62
76
  } : void 0, downloadStorageObject);
63
77
  const api = Object.assign({
64
78
  adapterName: adapterCapabilities.adapterName ?? core.adapterName,
65
- analytics,
79
+ insights,
66
80
  apiKeys,
67
81
  handlers
68
82
  }, core.api);
@@ -83,4 +97,4 @@ function createHotUpdater(options) {
83
97
  return createHotUpdaterCore(options).api;
84
98
  }
85
99
  //#endregion
86
- export { createHotUpdater, getHotUpdaterCoreMetadata };
100
+ export { createHotUpdater, createHotUpdaterCore, getHotUpdaterCoreMetadata, hotUpdaterCoreMetadata };
@@ -2,9 +2,9 @@ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
2
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
3
3
  let _hot_updater_core = require("@hot-updater/core");
4
4
  let node_crypto = require("node:crypto");
5
- node_crypto = require_runtime.__toESM(node_crypto);
5
+ node_crypto = require_runtime.__toESM(node_crypto, 1);
6
6
  let node_path = require("node:path");
7
- node_path = require_runtime.__toESM(node_path);
7
+ node_path = require_runtime.__toESM(node_path, 1);
8
8
  let node_util = require("node:util");
9
9
  let node_zlib = require("node:zlib");
10
10
  let _hot_updater_bsdiff = require("@hot-updater/bsdiff");
@@ -1,5 +1,4 @@
1
1
  import { Bundle, BundleRepository, StoragePluginWith } from "@hot-updater/plugin-core";
2
-
3
2
  //#region src/db/createBundleDiff.d.ts
4
3
  interface CreateBundleDiffInput {
5
4
  baseBundleId: string;
@@ -12,9 +11,6 @@ interface CreateBundleDiffDependencies {
12
11
  interface CreateBundleDiffOptions {
13
12
  makePrimary?: boolean;
14
13
  }
15
- declare function createBundleDiff({
16
- baseBundleId,
17
- bundleId
18
- }: CreateBundleDiffInput, deps: CreateBundleDiffDependencies, options?: CreateBundleDiffOptions): Promise<Bundle>;
14
+ declare function createBundleDiff({ baseBundleId, bundleId }: CreateBundleDiffInput, deps: CreateBundleDiffDependencies, options?: CreateBundleDiffOptions): Promise<Bundle>;
19
15
  //#endregion
20
16
  export { CreateBundleDiffDependencies, CreateBundleDiffInput, CreateBundleDiffOptions, createBundleDiff };