@hot-updater/server 1.0.0-rc.1 → 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.
- package/dist/_virtual/_rolldown/runtime.cjs +1 -1
- package/dist/adapters/databaseConstraintErrors.cjs +0 -1
- package/dist/adapters/databasePluginUtils.cjs +14 -1
- package/dist/adapters/databasePluginUtils.mjs +14 -2
- package/dist/adapters/drizzle.cjs +8 -3
- package/dist/adapters/drizzle.d.cts +0 -1
- package/dist/adapters/drizzle.d.mts +0 -1
- package/dist/adapters/drizzle.mjs +9 -3
- package/dist/adapters/drizzleCrud.cjs +93 -3
- package/dist/adapters/drizzleCrud.mjs +93 -5
- package/dist/adapters/drizzleLazyDB.cjs +2 -0
- package/dist/adapters/drizzleLazyDB.mjs +2 -0
- package/dist/adapters/drizzleQuery.cjs +3 -2
- package/dist/adapters/drizzleQuery.mjs +3 -1
- package/dist/adapters/kysely.cjs +1 -1
- package/dist/adapters/kysely.d.cts +0 -1
- package/dist/adapters/kysely.d.mts +0 -1
- package/dist/adapters/kysely.mjs +2 -1
- package/dist/adapters/kyselyCrud.cjs +44 -5
- package/dist/adapters/kyselyCrud.mjs +45 -6
- package/dist/adapters/kyselyQuery.cjs +2 -2
- package/dist/adapters/kyselyQuery.mjs +2 -1
- package/dist/adapters/mongodb.cjs +36 -1
- package/dist/adapters/mongodb.d.cts +1 -1
- package/dist/adapters/mongodb.d.mts +1 -1
- package/dist/adapters/mongodb.mjs +36 -0
- package/dist/adapters/mongodbCollections.cjs +2 -0
- package/dist/adapters/mongodbCollections.mjs +2 -0
- package/dist/adapters/mongodbQuery.cjs +17 -4
- package/dist/adapters/mongodbQuery.mjs +17 -4
- package/dist/adapters/mongodbReads.cjs +88 -30
- package/dist/adapters/mongodbReads.mjs +88 -29
- package/dist/adapters/mongodbWrites.cjs +1 -2
- package/dist/adapters/mongodbWrites.mjs +1 -1
- package/dist/adapters/prisma.cjs +44 -7
- package/dist/adapters/prisma.d.cts +0 -1
- package/dist/adapters/prisma.d.mts +0 -1
- package/dist/adapters/prisma.mjs +44 -6
- package/dist/adapters/prismaInsights.cjs +99 -0
- package/dist/adapters/prismaInsights.mjs +97 -0
- package/dist/adapters/prismaQuery.cjs +0 -1
- package/dist/adapters/prismaRows.cjs +7 -8
- package/dist/adapters/prismaRows.mjs +8 -8
- package/dist/apiKeys.cjs +6 -2
- package/dist/apiKeys.d.cts +0 -1
- package/dist/apiKeys.d.mts +0 -1
- package/dist/apiKeys.mjs +3 -3
- package/dist/createHotUpdaterCore.cjs +24 -9
- package/dist/createHotUpdaterCore.d.cts +1 -1
- package/dist/createHotUpdaterCore.d.mts +1 -1
- package/dist/createHotUpdaterCore.mjs +23 -9
- package/dist/db/createBundleDiff.cjs +2 -2
- package/dist/db/createBundleDiff.d.cts +1 -5
- package/dist/db/createBundleDiff.d.mts +1 -5
- package/dist/db/databasePluginCore.cjs +0 -1
- package/dist/db/fixedMigrator.cjs +2 -2
- package/dist/db/fixedMigrator.mjs +2 -2
- package/dist/db/fixedMigratorMongo.cjs +6 -4
- package/dist/db/fixedMigratorMongo.mjs +6 -4
- package/dist/db/index.d.cts +0 -1
- package/dist/db/index.d.mts +0 -1
- package/dist/db/releaseCatalog.cjs +0 -1
- package/dist/db/releaseCatalog.d.cts +0 -1
- package/dist/db/releaseCatalog.d.mts +0 -1
- package/dist/db/schema/insightsCollation.cjs +14 -0
- package/dist/db/schema/insightsCollation.mjs +14 -0
- package/dist/db/schema/sql.cjs +11 -7
- package/dist/db/schema/sql.mjs +8 -8
- package/dist/db/schemaGenerators.cjs +29 -9
- package/dist/db/schemaGenerators.mjs +29 -9
- package/dist/db/schemaReadiness.cjs +2 -0
- package/dist/db/schemaReadiness.d.cts +1 -0
- package/dist/db/schemaReadiness.d.mts +1 -0
- package/dist/db/schemaReadiness.mjs +2 -0
- package/dist/db/sqlMigrationExecution.cjs +1 -1
- package/dist/db/sqlMigrationExecution.mjs +1 -0
- package/dist/db/types.cjs +3 -1
- package/dist/db/types.d.cts +3 -6
- package/dist/db/types.d.mts +3 -6
- package/dist/db/types.mjs +2 -2
- package/dist/db/updateArtifacts.cjs +0 -1
- package/dist/handler.d.cts +1 -2
- package/dist/handler.d.mts +1 -2
- package/dist/handlerReleaseCatalogRoutes.cjs +0 -1
- package/dist/handlerReleaseManagementRoutes.cjs +0 -1
- package/dist/handlerTypes.d.cts +0 -1
- package/dist/handlerTypes.d.mts +0 -1
- package/dist/handlerVersionRoutes.d.cts +1 -0
- package/dist/handlerVersionRoutes.d.mts +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +1 -1
- package/dist/insights/domain.d.cts +41 -70
- package/dist/insights/domain.d.mts +41 -70
- package/dist/insights/errors.cjs +1 -8
- package/dist/insights/errors.mjs +2 -8
- package/dist/insights/eventInput.cjs +52 -7
- package/dist/insights/eventInput.mjs +51 -8
- package/dist/insights/provider.cjs +332 -0
- package/dist/insights/provider.d.cts +6 -0
- package/dist/insights/provider.d.mts +6 -0
- package/dist/insights/provider.mjs +332 -0
- package/dist/insights/queryInput.cjs +78 -43
- package/dist/insights/queryInput.mjs +76 -40
- package/dist/insights/routes.cjs +20 -25
- package/dist/insights/routes.mjs +22 -27
- package/dist/insights/types.d.cts +27 -12
- package/dist/insights/types.d.mts +27 -12
- package/dist/node.d.cts +0 -1
- package/dist/node.d.mts +0 -1
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/schema/index.cjs +17 -3
- package/dist/schema/index.mjs +4 -4
- package/dist/schema/v1_0_0.cjs +64 -35
- package/dist/schema/v1_0_0.mjs +64 -36
- package/dist/storageAccess.cjs +0 -1
- package/dist/types/index.d.cts +0 -1
- package/dist/types/index.d.mts +0 -1
- package/package.json +7 -7
- package/src/adapters/databasePluginTestDatabase.ts +15 -5
- package/src/adapters/databasePluginUtils.ts +24 -0
- package/src/adapters/drizzle.spec.ts +203 -5
- package/src/adapters/drizzle.ts +15 -3
- package/src/adapters/drizzleCrud.ts +200 -9
- package/src/adapters/drizzleLazyDB.ts +33 -6
- package/src/adapters/kysely.spec.ts +62 -0
- package/src/adapters/kysely.ts +7 -1
- package/src/adapters/kyselyCrud.ts +115 -7
- package/src/adapters/kyselyInsights.spec.ts +168 -0
- package/src/adapters/mongodb.integration.spec.ts +483 -0
- package/src/adapters/mongodb.spec.ts +89 -0
- package/src/adapters/mongodb.ts +59 -1
- package/src/adapters/mongodbCollections.ts +16 -0
- package/src/adapters/mongodbQuery.ts +22 -3
- package/src/adapters/mongodbReads.ts +78 -2
- package/src/adapters/mongodbTestClient.ts +107 -6
- package/src/adapters/mongodbTestFilter.ts +5 -1
- package/src/adapters/mongodbWrites.ts +1 -0
- package/src/adapters/prisma.spec.ts +270 -0
- package/src/adapters/prisma.ts +75 -2
- package/src/adapters/prismaInsights.ts +190 -0
- package/src/adapters/prismaRows.ts +17 -10
- package/src/adapters/prismaTestClient.ts +89 -7
- package/src/apiKeys.integration.spec.ts +1 -1
- package/src/createHotUpdaterCore.ts +21 -7
- package/src/db/databasePluginUpdateCheck.bench.ts +10 -0
- package/src/db/fixedMigrator.spec.ts +63 -0
- package/src/db/fixedMigratorMongo.spec.ts +70 -9
- package/src/db/fixedMigratorMongo.ts +10 -10
- package/src/db/index.spec.ts +6 -1
- package/src/db/schema/insightsCollation.ts +21 -0
- package/src/db/schema/sql.ts +8 -5
- package/src/db/schemaGenerators.ts +42 -13
- package/src/db/types.spec.ts +8 -0
- package/src/db/types.ts +10 -4
- package/src/handler-standalone.integration.spec.ts +5 -7
- package/src/index.ts +2 -2
- package/src/insights/domain.ts +44 -77
- package/src/insights/errors.ts +0 -7
- package/src/insights/eventInput.ts +55 -5
- package/src/insights/insights.integration.spec.ts +348 -17
- package/src/insights/provider.spec.ts +396 -0
- package/src/insights/provider.ts +611 -0
- package/src/insights/queryInput.ts +113 -73
- package/src/insights/routes.ts +37 -56
- package/src/insights/types.ts +47 -36
- package/src/schema/dsl-all-versions.spec.ts +1 -1
- package/src/schema/v1_0_0.spec.ts +77 -3
- package/src/schema/v1_0_0.ts +83 -37
- package/dist/insights/bounded/activeOverview.cjs +0 -87
- package/dist/insights/bounded/activeOverview.mjs +0 -85
- package/dist/insights/bounded/installationSearch.cjs +0 -42
- package/dist/insights/bounded/installationSearch.mjs +0 -42
- package/dist/insights/bounded/persistence.cjs +0 -39
- package/dist/insights/bounded/persistence.mjs +0 -38
- package/dist/insights/bounded/provider.cjs +0 -170
- package/dist/insights/bounded/provider.d.cts +0 -7
- package/dist/insights/bounded/provider.d.mts +0 -7
- package/dist/insights/bounded/provider.mjs +0 -170
- package/dist/insights/bounded/scan.cjs +0 -144
- package/dist/insights/bounded/scan.mjs +0 -138
- package/dist/insights/persistence.d.cts +0 -6
- package/dist/insights/persistence.d.mts +0 -6
- package/src/insights/bounded/activeOverview.spec.ts +0 -189
- package/src/insights/bounded/activeOverview.ts +0 -148
- package/src/insights/bounded/installationSearch.spec.ts +0 -130
- package/src/insights/bounded/installationSearch.ts +0 -69
- package/src/insights/bounded/persistence.ts +0 -43
- package/src/insights/bounded/provider.spec.ts +0 -219
- package/src/insights/bounded/provider.ts +0 -229
- package/src/insights/bounded/scan.ts +0 -235
- package/src/insights/persistence.ts +0 -10
|
@@ -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,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
|
|
96
|
-
|
|
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
|
-
|
|
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
|
|
95
|
-
|
|
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
|
-
|
|
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;
|
package/dist/apiKeys.d.cts
CHANGED
package/dist/apiKeys.d.mts
CHANGED
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("./insights/
|
|
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,27 +24,41 @@ 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
|
|
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
|
|
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
42
|
const insights = require_provider.createInsightsProvider({
|
|
42
|
-
async
|
|
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.insights.
|
|
57
|
+
return plugin.models.insights.countLatestEvents(input);
|
|
45
58
|
},
|
|
46
|
-
async
|
|
59
|
+
async countEvents(input) {
|
|
47
60
|
await assertSchemaReady();
|
|
48
|
-
return plugin.models.insights.
|
|
61
|
+
return plugin.models.insights.countEvents(input);
|
|
49
62
|
}
|
|
50
63
|
});
|
|
51
64
|
const apiKeys = require_apiKeys.createApiKeyManagement({
|
|
@@ -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,9 +1,9 @@
|
|
|
1
1
|
import { ApiKeyManagementAPI } from "./apiKeys.cjs";
|
|
2
2
|
import { HotUpdaterHandlers } from "./handlerTypes.cjs";
|
|
3
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;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ApiKeyManagementAPI } from "./apiKeys.mjs";
|
|
2
2
|
import { HotUpdaterHandlers } from "./handlerTypes.mjs";
|
|
3
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;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHotUpdaterHandlers } from "./handler.mjs";
|
|
2
|
-
import { createInsightsProvider } from "./insights/
|
|
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,27 +24,41 @@ 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
|
|
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
|
|
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
42
|
const insights = createInsightsProvider({
|
|
41
|
-
async
|
|
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.insights.
|
|
57
|
+
return plugin.models.insights.countLatestEvents(input);
|
|
44
58
|
},
|
|
45
|
-
async
|
|
59
|
+
async countEvents(input) {
|
|
46
60
|
await assertSchemaReady();
|
|
47
|
-
return plugin.models.insights.
|
|
61
|
+
return plugin.models.insights.countEvents(input);
|
|
48
62
|
}
|
|
49
63
|
});
|
|
50
64
|
const apiKeys = createApiKeyManagement({
|
|
@@ -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 };
|
|
@@ -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 };
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
1
|
const require_types = require("../schema/types.cjs");
|
|
3
2
|
const require_fixedMigratorShared = require("./fixedMigratorShared.cjs");
|
|
4
3
|
const require_sql = require("./schema/sql.cjs");
|
|
5
4
|
const require_sqlOperations = require("./schema/sqlOperations.cjs");
|
|
6
5
|
const require_sqlMigrationExecution = require("./sqlMigrationExecution.cjs");
|
|
7
|
-
require("./fixedMigratorMongo.cjs");
|
|
6
|
+
const require_fixedMigratorMongo = require("./fixedMigratorMongo.cjs");
|
|
8
7
|
let kysely = require("kysely");
|
|
9
8
|
//#region src/db/fixedMigrator.ts
|
|
10
9
|
const isMissingSettingsTableError = (error) => {
|
|
@@ -77,3 +76,4 @@ const createKyselyMigrator = ({ db, provider, relationMode = "foreign-keys" }) =
|
|
|
77
76
|
};
|
|
78
77
|
//#endregion
|
|
79
78
|
exports.createKyselyMigrator = createKyselyMigrator;
|
|
79
|
+
exports.createMongoMigrator = require_fixedMigratorMongo.createMongoMigrator;
|
|
@@ -3,7 +3,7 @@ import { assertCurrentOrEmptySchemaVersion, assertSupportedMigrationMode, getEmp
|
|
|
3
3
|
import { createTableSql } from "./schema/sql.mjs";
|
|
4
4
|
import { createSqlCreateOperations, getSettingsInsertSql } from "./schema/sqlOperations.mjs";
|
|
5
5
|
import { executeMigrationStatements } from "./sqlMigrationExecution.mjs";
|
|
6
|
-
import "./fixedMigratorMongo.mjs";
|
|
6
|
+
import { createMongoMigrator } from "./fixedMigratorMongo.mjs";
|
|
7
7
|
import { sql } from "kysely";
|
|
8
8
|
//#region src/db/fixedMigrator.ts
|
|
9
9
|
const isMissingSettingsTableError = (error) => {
|
|
@@ -75,4 +75,4 @@ const createKyselyMigrator = ({ db, provider, relationMode = "foreign-keys" }) =
|
|
|
75
75
|
};
|
|
76
76
|
};
|
|
77
77
|
//#endregion
|
|
78
|
-
export { createKyselyMigrator };
|
|
78
|
+
export { createKyselyMigrator, createMongoMigrator };
|
|
@@ -259,19 +259,21 @@ const createMongoMigrator = (client) => {
|
|
|
259
259
|
await ensureSettingsKeyIndex();
|
|
260
260
|
for (const table of require_registry.hotUpdaterSchema.tables) {
|
|
261
261
|
if (table.internal) continue;
|
|
262
|
+
const isInsights = table.ormName === "bundle_events" || table.ormName === "bundle_event_heads";
|
|
262
263
|
const collection = db.collection(table.ormName);
|
|
264
|
+
const collation = isInsights ? { locale: "simple" } : void 0;
|
|
263
265
|
const primaryKey = table.columns.find((column) => column.primaryKey);
|
|
264
266
|
if (!primaryKey) throw new Error(`MongoDB table ${table.ormName} does not define a primary key.`);
|
|
265
267
|
const idIndexName = `${table.ormName}_${primaryKey.ormName}_idx`;
|
|
266
|
-
const existingIdIndex = (await collection.listIndexes().toArray()).find(({ name }) => name === idIndexName);
|
|
267
|
-
if (existingIdIndex && existingIdIndex.unique !== true) await collection.dropIndex(idIndexName);
|
|
268
268
|
await collection.createIndex({ [primaryKey.ormName]: 1 }, {
|
|
269
269
|
name: idIndexName,
|
|
270
|
-
unique: true
|
|
270
|
+
unique: true,
|
|
271
|
+
...collation ? { collation } : {}
|
|
271
272
|
});
|
|
272
273
|
for (const index of (table.indexes ?? []).filter((item) => require_registry.schemaIndexAppliesToProvider(item, "mongodb"))) await collection.createIndex(Object.fromEntries(index.columns.map((column) => [column, 1])), {
|
|
273
274
|
name: index.name,
|
|
274
|
-
...index.unique ? { unique: true } : {}
|
|
275
|
+
...index.unique ? { unique: true } : {},
|
|
276
|
+
...collation ? { collation } : {}
|
|
275
277
|
});
|
|
276
278
|
}
|
|
277
279
|
},
|