@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.
- package/dist/adapters/databaseConstraintErrors.cjs +23 -0
- package/dist/adapters/databaseConstraintErrors.mjs +21 -0
- package/dist/adapters/databasePluginUtils.cjs +117 -0
- package/dist/adapters/databasePluginUtils.mjs +106 -0
- package/dist/adapters/drizzle.cjs +53 -176
- package/dist/adapters/drizzle.d.cts +6 -4
- package/dist/adapters/drizzle.d.mts +6 -4
- package/dist/adapters/drizzle.mjs +54 -177
- package/dist/adapters/drizzleCrud.cjs +250 -0
- package/dist/adapters/drizzleCrud.mjs +249 -0
- package/dist/adapters/drizzleLazyDB.cjs +84 -36
- package/dist/adapters/drizzleLazyDB.mjs +84 -36
- package/dist/adapters/drizzleQuery.cjs +68 -0
- package/dist/adapters/drizzleQuery.mjs +67 -0
- package/dist/adapters/kysely.cjs +18 -138
- package/dist/adapters/kysely.d.cts +3 -12
- package/dist/adapters/kysely.d.mts +3 -12
- package/dist/adapters/kysely.mjs +19 -139
- package/dist/adapters/kyselyCrud.cjs +254 -0
- package/dist/adapters/kyselyCrud.mjs +253 -0
- package/dist/adapters/kyselyQuery.cjs +56 -0
- package/dist/adapters/kyselyQuery.mjs +55 -0
- package/dist/adapters/mongodb.cjs +21 -174
- package/dist/adapters/mongodb.d.cts +3 -2
- package/dist/adapters/mongodb.d.mts +3 -2
- package/dist/adapters/mongodb.mjs +21 -174
- package/dist/adapters/mongodbCollections.cjs +36 -0
- package/dist/adapters/mongodbCollections.mjs +30 -0
- package/dist/adapters/mongodbQuery.cjs +77 -0
- package/dist/adapters/mongodbQuery.mjs +70 -0
- package/dist/adapters/mongodbReads.cjs +148 -0
- package/dist/adapters/mongodbReads.mjs +147 -0
- package/dist/adapters/mongodbWrites.cjs +134 -0
- package/dist/adapters/mongodbWrites.mjs +133 -0
- package/dist/adapters/prisma.cjs +205 -180
- package/dist/adapters/prisma.d.cts +3 -3
- package/dist/adapters/prisma.d.mts +3 -3
- package/dist/adapters/prisma.mjs +206 -181
- package/dist/adapters/prismaQuery.cjs +58 -0
- package/dist/adapters/prismaQuery.mjs +56 -0
- package/dist/adapters/prismaRows.cjs +198 -0
- package/dist/adapters/prismaRows.mjs +188 -0
- package/dist/apiKeys.cjs +139 -0
- package/dist/apiKeys.d.cts +50 -0
- package/dist/apiKeys.d.mts +50 -0
- package/dist/apiKeys.mjs +133 -0
- package/dist/createHotUpdaterCore.cjs +48 -26
- package/dist/createHotUpdaterCore.d.cts +49 -17
- package/dist/createHotUpdaterCore.d.mts +49 -17
- package/dist/createHotUpdaterCore.mjs +51 -29
- package/dist/db/createBundleDiff.cjs +45 -68
- package/dist/db/createBundleDiff.d.cts +3 -3
- package/dist/db/createBundleDiff.d.mts +3 -3
- package/dist/db/createBundleDiff.mjs +47 -68
- package/dist/db/databasePluginCore.cjs +138 -0
- package/dist/db/databasePluginCore.mjs +137 -0
- package/dist/db/fixedMigrator.cjs +36 -93
- package/dist/db/fixedMigrator.mjs +36 -93
- package/dist/db/fixedMigratorMongo.cjs +319 -0
- package/dist/db/fixedMigratorMongo.mjs +319 -0
- package/dist/db/fixedMigratorShared.cjs +23 -0
- package/dist/db/fixedMigratorShared.mjs +18 -0
- package/dist/db/mongoMigrationExecution.cjs +11 -0
- package/dist/db/mongoMigrationExecution.mjs +11 -0
- package/dist/db/releaseCatalog.cjs +66 -0
- package/dist/db/releaseCatalog.d.cts +17 -0
- package/dist/db/releaseCatalog.d.mts +17 -0
- package/dist/db/releaseCatalog.mjs +64 -0
- package/dist/db/schema/mongodb.cjs +14 -6
- package/dist/db/schema/mongodb.mjs +14 -6
- package/dist/db/schema/registry.cjs +0 -2
- package/dist/db/schema/registry.mjs +1 -2
- package/dist/db/schema/sql.cjs +31 -14
- package/dist/db/schema/sql.mjs +32 -13
- package/dist/db/schema/sqlOperations.cjs +4 -4
- package/dist/db/schema/sqlOperations.mjs +5 -5
- package/dist/db/schemaGenerators.cjs +52 -18
- package/dist/db/schemaGenerators.mjs +52 -18
- package/dist/db/schemaReadiness.cjs +4 -3
- package/dist/db/schemaReadiness.mjs +4 -3
- package/dist/db/sqlMigrationExecution.cjs +67 -0
- package/dist/db/sqlMigrationExecution.mjs +66 -0
- package/dist/db/types.cjs +2 -6
- package/dist/db/types.d.cts +60 -16
- package/dist/db/types.d.mts +60 -16
- package/dist/db/types.mjs +3 -6
- package/dist/db/updateArtifacts.cjs +114 -60
- package/dist/db/updateArtifacts.mjs +117 -62
- package/dist/handler.cjs +108 -282
- package/dist/handler.d.cts +3 -46
- package/dist/handler.d.mts +3 -46
- package/dist/handler.mjs +107 -281
- package/dist/handlerBundleRoutes.cjs +155 -0
- package/dist/handlerBundleRoutes.mjs +155 -0
- package/dist/handlerErrors.cjs +9 -0
- package/dist/handlerErrors.mjs +9 -0
- package/dist/handlerParameters.cjs +39 -0
- package/dist/handlerParameters.mjs +34 -0
- package/dist/handlerReleaseCatalogRoutes.cjs +111 -0
- package/dist/handlerReleaseCatalogRoutes.mjs +110 -0
- package/dist/handlerReleaseManagementRoutes.cjs +125 -0
- package/dist/handlerReleaseManagementRoutes.mjs +124 -0
- package/dist/handlerTypes.d.cts +63 -0
- package/dist/handlerTypes.d.mts +63 -0
- package/dist/handlerVersionRoutes.cjs +10 -0
- package/dist/handlerVersionRoutes.d.cts +4 -0
- package/dist/handlerVersionRoutes.d.mts +4 -0
- package/dist/handlerVersionRoutes.mjs +9 -0
- package/dist/index.cjs +10 -1
- package/dist/index.d.cts +9 -3
- package/dist/index.d.mts +9 -3
- package/dist/index.mjs +5 -2
- package/dist/insights/bounded/activeOverview.cjs +87 -0
- package/dist/insights/bounded/activeOverview.mjs +85 -0
- package/dist/insights/bounded/installationSearch.cjs +42 -0
- package/dist/insights/bounded/installationSearch.mjs +42 -0
- package/dist/insights/bounded/persistence.cjs +39 -0
- package/dist/insights/bounded/persistence.mjs +38 -0
- package/dist/insights/bounded/provider.cjs +170 -0
- package/dist/insights/bounded/provider.d.cts +7 -0
- package/dist/insights/bounded/provider.d.mts +7 -0
- package/dist/insights/bounded/provider.mjs +170 -0
- package/dist/insights/bounded/scan.cjs +144 -0
- package/dist/insights/bounded/scan.mjs +138 -0
- package/dist/insights/domain.d.cts +121 -0
- package/dist/insights/domain.d.mts +121 -0
- package/dist/insights/errors.cjs +22 -0
- package/dist/insights/errors.mjs +20 -0
- package/dist/insights/eventInput.cjs +111 -0
- package/dist/insights/eventInput.mjs +111 -0
- package/dist/insights/persistence.d.cts +6 -0
- package/dist/insights/persistence.d.mts +6 -0
- package/dist/insights/queryInput.cjs +58 -0
- package/dist/insights/queryInput.mjs +55 -0
- package/dist/insights/routes.cjs +63 -0
- package/dist/insights/routes.mjs +61 -0
- package/dist/insights/types.d.cts +17 -0
- package/dist/insights/types.d.mts +17 -0
- package/dist/node.cjs +19 -12
- package/dist/node.d.cts +15 -10
- package/dist/node.d.mts +15 -10
- package/dist/node.mjs +19 -13
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/schema/dsl.cjs +19 -2
- package/dist/schema/dsl.mjs +17 -3
- package/dist/schema/index.cjs +1 -8
- package/dist/schema/index.mjs +2 -8
- package/dist/schema/types.cjs +3 -1
- package/dist/schema/types.mjs +3 -2
- package/dist/schema/v1_0_0.cjs +364 -0
- package/dist/schema/v1_0_0.mjs +357 -0
- package/dist/storageAccess.cjs +69 -25
- package/dist/storageAccess.mjs +68 -25
- package/dist/types/index.d.cts +4 -3
- package/dist/types/index.d.mts +5 -4
- package/package.json +8 -7
- package/src/adapters/databaseConstraintErrors.ts +25 -0
- package/src/adapters/databasePluginTestDatabase.ts +106 -0
- package/src/adapters/databasePluginUtils.spec.ts +29 -0
- package/src/adapters/databasePluginUtils.ts +214 -0
- package/src/adapters/drizzle.spec.ts +208 -47
- package/src/adapters/drizzle.ts +106 -293
- package/src/adapters/drizzleCrud.ts +419 -0
- package/src/adapters/drizzleLazyDB.ts +206 -100
- package/src/adapters/drizzleQuery.ts +164 -0
- package/src/adapters/kysely.spec.ts +126 -88
- package/src/adapters/kysely.ts +76 -334
- package/src/adapters/kyselyCrud.ts +588 -0
- package/src/adapters/kyselyQuery.ts +128 -0
- package/src/adapters/mongodb.spec.ts +141 -0
- package/src/adapters/mongodb.ts +60 -288
- package/src/adapters/mongodbCollections.ts +62 -0
- package/src/adapters/mongodbQuery.ts +226 -0
- package/src/adapters/mongodbReads.ts +311 -0
- package/src/adapters/mongodbRows.spec.ts +64 -0
- package/src/adapters/mongodbRows.ts +118 -0
- package/src/adapters/mongodbTestClient.ts +342 -0
- package/src/adapters/mongodbTestFilter.ts +166 -0
- package/src/adapters/mongodbWrites.ts +260 -0
- package/src/adapters/prisma.spec.ts +196 -0
- package/src/adapters/prisma.ts +417 -292
- package/src/adapters/prismaQuery.ts +129 -0
- package/src/adapters/prismaRows.spec.ts +98 -0
- package/src/adapters/prismaRows.ts +301 -0
- package/src/adapters/prismaTestClient.ts +396 -0
- package/src/apiKeys.integration.spec.ts +192 -0
- package/src/apiKeys.spec.ts +162 -0
- package/src/apiKeys.ts +220 -0
- package/src/createHotUpdaterCore.ts +164 -100
- package/src/db/bundleRows.spec.ts +164 -0
- package/src/db/bundleRows.ts +10 -140
- package/src/db/createBundleDiff.spec.ts +172 -127
- package/src/db/createBundleDiff.ts +91 -110
- package/src/db/databasePluginCore.spec.ts +62 -0
- package/src/db/databasePluginCore.testFixtures.ts +76 -0
- package/src/db/databasePluginCore.ts +185 -0
- package/src/db/databasePluginUpdateCheck.bench.ts +107 -0
- package/src/db/fixedMigrator.spec.ts +184 -42
- package/src/db/fixedMigrator.ts +64 -205
- package/src/db/fixedMigratorMongo.spec.ts +192 -0
- package/src/db/fixedMigratorMongo.ts +425 -0
- package/src/db/fixedMigratorShared.ts +36 -0
- package/src/db/hotUpdaterSchema.ts +0 -1
- package/src/db/index.spec.ts +333 -1025
- package/src/db/mongoMigrationExecution.ts +23 -0
- package/src/db/node-sqlite.d.ts +25 -0
- package/src/db/releaseCatalog.ts +148 -0
- package/src/db/schema/mongodb.ts +20 -6
- package/src/db/schema/sql.ts +52 -11
- package/src/db/schema/sqlOperations.ts +5 -4
- package/src/db/schemaGenerators.ts +107 -23
- package/src/db/schemaReadiness.ts +2 -1
- package/src/db/sqlMigrationExecution.spec.ts +65 -0
- package/src/db/sqlMigrationExecution.ts +108 -0
- package/src/db/types.spec.ts +55 -0
- package/src/db/types.ts +129 -65
- package/src/db/updateArtifacts.spec.ts +359 -0
- package/src/db/updateArtifacts.ts +290 -126
- package/src/handler-standalone.integration.spec.ts +401 -364
- package/src/handler.spec.ts +137 -582
- package/src/handler.testFixtures.ts +30 -0
- package/src/handler.ts +218 -616
- package/src/handlerAuth.integration.spec.ts +33 -0
- package/src/handlerBundleRoutes.ts +259 -0
- package/src/handlerErrors.ts +7 -0
- package/src/handlerManagement.spec.ts +262 -0
- package/src/handlerParameters.ts +105 -0
- package/src/handlerReleaseCatalogRoutes.ts +154 -0
- package/src/handlerReleaseManagementRoutes.ts +213 -0
- package/src/handlerTypes.ts +96 -0
- package/src/handlerVersionRoutes.ts +12 -0
- package/src/index.ts +22 -2
- package/src/insights/bounded/activeOverview.spec.ts +189 -0
- package/src/insights/bounded/activeOverview.ts +148 -0
- package/src/insights/bounded/installationSearch.spec.ts +130 -0
- package/src/insights/bounded/installationSearch.ts +69 -0
- package/src/insights/bounded/persistence.ts +43 -0
- package/src/insights/bounded/provider.spec.ts +219 -0
- package/src/insights/bounded/provider.ts +229 -0
- package/src/insights/bounded/scan.ts +235 -0
- package/src/insights/domain.ts +139 -0
- package/src/insights/errors.ts +18 -0
- package/src/insights/eventInput.ts +168 -0
- package/src/insights/insights.integration.spec.ts +144 -0
- package/src/insights/persistence.ts +10 -0
- package/src/insights/queryInput.ts +102 -0
- package/src/insights/routes.ts +123 -0
- package/src/insights/types.ts +44 -0
- package/src/node.spec.ts +79 -10
- package/src/node.ts +20 -17
- package/src/releaseCatalogRoutes.integration.spec.ts +238 -0
- package/src/runtime.spec.ts +126 -959
- package/src/runtime.testFixtures.ts +71 -0
- package/src/schema/dsl-all-versions.spec.ts +26 -17
- package/src/schema/dsl.ts +41 -2
- package/src/schema/index.ts +3 -9
- package/src/schema/types.ts +9 -3
- package/src/schema/v1_0_0.spec.ts +146 -0
- package/src/schema/v1_0_0.ts +465 -0
- package/src/storageAccess.spec.ts +127 -32
- package/src/storageAccess.ts +106 -55
- package/src/types/index.ts +2 -1
- package/dist/db/bundleRows.cjs +0 -82
- package/dist/db/bundleRows.d.cts +0 -33
- package/dist/db/bundleRows.d.mts +0 -33
- package/dist/db/bundleRows.mjs +0 -79
- package/dist/db/pluginCore.cjs +0 -242
- package/dist/db/pluginCore.mjs +0 -241
- package/dist/db/schema/sqlMigrations.cjs +0 -74
- package/dist/db/schema/sqlMigrations.mjs +0 -73
- package/dist/db/schemaEnhancements.cjs +0 -20
- package/dist/db/schemaEnhancements.mjs +0 -19
- package/dist/route.cjs +0 -7
- package/dist/route.mjs +0 -7
- package/dist/schema/v0_21_0.cjs +0 -38
- package/dist/schema/v0_21_0.mjs +0 -37
- package/dist/schema/v0_29_0.cjs +0 -45
- package/dist/schema/v0_29_0.mjs +0 -44
- package/dist/schema/v0_31_0.cjs +0 -82
- package/dist/schema/v0_31_0.mjs +0 -80
- package/src/db/pluginCore.spec.ts +0 -1095
- package/src/db/pluginCore.ts +0 -475
- package/src/db/pluginUpdateCheck.bench.ts +0 -254
- package/src/db/schema/sqlMigrations.ts +0 -219
- package/src/db/schemaEnhancements.ts +0 -55
- package/src/route.ts +0 -7
- package/src/schema/v0_21_0.ts +0 -52
- package/src/schema/v0_29_0.ts +0 -62
- package/src/schema/v0_31_0.spec.ts +0 -73
- package/src/schema/v0_31_0.ts +0 -120
|
@@ -1,135 +1,78 @@
|
|
|
1
|
-
import { HOT_UPDATER_SCHEMA_VERSION, HOT_UPDATER_SETTINGS_TABLE } from "../schema/types.mjs";
|
|
2
|
-
import {
|
|
1
|
+
import { HOT_UPDATER_CORE_SCHEMA_KEY, HOT_UPDATER_SCHEMA_VERSION, HOT_UPDATER_SETTINGS_TABLE } from "../schema/types.mjs";
|
|
2
|
+
import { assertCurrentOrEmptySchemaVersion, assertSupportedMigrationMode, getEmptyMigrationResult, inferLegacyCoreSchemaVersion, isCurrentSchemaVersion } from "./fixedMigratorShared.mjs";
|
|
3
3
|
import { createTableSql } from "./schema/sql.mjs";
|
|
4
|
-
import { createMongoMigrationOperations } from "./schema/mongodb.mjs";
|
|
5
|
-
import { createV029AlterSql, createV031AlterSql } from "./schema/sqlMigrations.mjs";
|
|
6
4
|
import { createSqlCreateOperations, getSettingsInsertSql } from "./schema/sqlOperations.mjs";
|
|
5
|
+
import { executeMigrationStatements } from "./sqlMigrationExecution.mjs";
|
|
6
|
+
import "./fixedMigratorMongo.mjs";
|
|
7
|
+
import { sql } from "kysely";
|
|
7
8
|
//#region src/db/fixedMigrator.ts
|
|
8
|
-
const getEmptyResult = () => ({
|
|
9
|
-
operations: [],
|
|
10
|
-
execute: async () => {},
|
|
11
|
-
getSQL: () => ""
|
|
12
|
-
});
|
|
13
|
-
const assertSupportedMigrationMode = (options) => {
|
|
14
|
-
if (options.mode === "from-database") throw new Error("Hot Updater migrations support only mode: 'from-schema'.");
|
|
15
|
-
};
|
|
16
9
|
const isMissingSettingsTableError = (error) => {
|
|
17
10
|
if (!(error instanceof Error)) return false;
|
|
18
11
|
const message = error.message.toLowerCase();
|
|
19
12
|
return message.includes("private_hot_updater_settings") && (message.includes("does not exist") || message.includes("no such table") || message.includes("doesn't exist") || message.includes("not found"));
|
|
20
13
|
};
|
|
21
|
-
const isMongoNamespaceExistsError = (error) => {
|
|
22
|
-
if (!(error instanceof Error)) return false;
|
|
23
|
-
const mongoError = error;
|
|
24
|
-
return mongoError.code === 48 || mongoError.codeName === "NamespaceExists";
|
|
25
|
-
};
|
|
26
|
-
const ignoreExistingCollection = (error) => {
|
|
27
|
-
if (isMongoNamespaceExistsError(error)) return;
|
|
28
|
-
throw error;
|
|
29
|
-
};
|
|
30
|
-
const toCustomOperations = (statements, settingsOperation) => [...statements.map((statement) => ({
|
|
31
|
-
type: "custom",
|
|
32
|
-
sql: statement
|
|
33
|
-
})), ...settingsOperation ? [settingsOperation] : []];
|
|
34
|
-
const assertSupportedSchemaVersion = (currentVersion) => {
|
|
35
|
-
if (currentVersion !== void 0 && currentVersion !== "0.21.0" && currentVersion !== "0.29.0") throw new Error(`Unsupported Hot Updater schema version: ${currentVersion}`);
|
|
36
|
-
};
|
|
37
14
|
const createKyselyMigrator = ({ db, provider, relationMode = "foreign-keys" }) => {
|
|
38
|
-
const
|
|
15
|
+
const getSetting = async (key) => {
|
|
39
16
|
try {
|
|
40
|
-
const row = await
|
|
41
|
-
|
|
17
|
+
const row = (await sql`select ${sql.ref("value")} from ${sql.table(HOT_UPDATER_SETTINGS_TABLE)} where ${sql.ref("key")} = ${key} limit 1`.execute(db)).rows[0];
|
|
18
|
+
if (!row) return void 0;
|
|
19
|
+
if (typeof row.value !== "string") throw new Error(`Invalid Hot Updater schema setting: ${key}`);
|
|
20
|
+
return row.value;
|
|
42
21
|
} catch (error) {
|
|
43
22
|
if (!isMissingSettingsTableError(error)) throw error;
|
|
44
23
|
return;
|
|
45
24
|
}
|
|
46
25
|
};
|
|
26
|
+
const getCoreVersion = () => getSetting(HOT_UPDATER_CORE_SCHEMA_KEY);
|
|
27
|
+
const getSchemaVersions = async () => {
|
|
28
|
+
return {
|
|
29
|
+
coreVersion: await getCoreVersion(),
|
|
30
|
+
legacyCoreVersion: inferLegacyCoreSchemaVersion(await getSetting("version"))
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
const getVersion = async () => {
|
|
34
|
+
const { coreVersion, legacyCoreVersion } = await getSchemaVersions();
|
|
35
|
+
return coreVersion ?? legacyCoreVersion;
|
|
36
|
+
};
|
|
47
37
|
const makeResult = async (options = {}) => {
|
|
48
38
|
assertSupportedMigrationMode(options);
|
|
49
|
-
const
|
|
50
|
-
if (
|
|
51
|
-
|
|
39
|
+
const { coreVersion, legacyCoreVersion } = await getSchemaVersions();
|
|
40
|
+
if (isCurrentSchemaVersion(coreVersion)) return getEmptyMigrationResult();
|
|
41
|
+
assertCurrentOrEmptySchemaVersion(coreVersion ?? legacyCoreVersion);
|
|
52
42
|
const settingsStatement = getSettingsInsertSql(provider);
|
|
53
43
|
const settingsOperation = options.updateSettings === false ? void 0 : {
|
|
54
44
|
type: "custom",
|
|
55
45
|
sql: settingsStatement
|
|
56
46
|
};
|
|
57
|
-
const
|
|
58
|
-
const statements = currentVersion === void 0 ? [...createTableSql(provider, relationMode), settingsStatement] : [
|
|
59
|
-
...currentVersion === "0.21.0" ? createV029AlterSql(provider) : [],
|
|
60
|
-
...currentVersion === "0.21.0" || currentVersion === "0.29.0" ? createV031AlterSql(provider, relationMode) : [],
|
|
61
|
-
...executableSettingsStatements
|
|
62
|
-
];
|
|
47
|
+
const statements = [...createTableSql(provider, relationMode), settingsStatement];
|
|
63
48
|
return {
|
|
64
|
-
operations:
|
|
49
|
+
operations: createSqlCreateOperations(provider, relationMode, settingsOperation),
|
|
65
50
|
getSQL: () => statements.map((statement) => `${statement};`).join("\n\n"),
|
|
66
|
-
execute:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
51
|
+
execute: () => executeMigrationStatements({
|
|
52
|
+
db,
|
|
53
|
+
provider,
|
|
54
|
+
statements
|
|
55
|
+
})
|
|
70
56
|
};
|
|
71
57
|
};
|
|
72
58
|
return {
|
|
73
59
|
getVersion,
|
|
74
60
|
getNameVariants: async () => void 0,
|
|
75
|
-
next: async () =>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
down: async () => {
|
|
79
|
-
throw new Error("No previous schema to migrate to.");
|
|
61
|
+
next: async () => {
|
|
62
|
+
const { coreVersion } = await getSchemaVersions();
|
|
63
|
+
return isCurrentSchemaVersion(coreVersion) ? void 0 : { version: HOT_UPDATER_SCHEMA_VERSION };
|
|
80
64
|
},
|
|
81
|
-
migrateTo: async (version, options) => {
|
|
82
|
-
if (version !== "0.31.0") throw new Error(`Invalid version ${version}`);
|
|
83
|
-
return makeResult(options);
|
|
84
|
-
},
|
|
85
|
-
migrateToLatest: makeResult
|
|
86
|
-
};
|
|
87
|
-
};
|
|
88
|
-
const createMongoMigrator = (client) => {
|
|
89
|
-
const settings = client.db().collection(HOT_UPDATER_SETTINGS_TABLE);
|
|
90
|
-
const getVersion = async () => {
|
|
91
|
-
const row = await settings.findOne({ key: "version" });
|
|
92
|
-
return typeof row?.value === "string" ? row.value : void 0;
|
|
93
|
-
};
|
|
94
|
-
const makeResult = async (options = {}) => {
|
|
95
|
-
assertSupportedMigrationMode(options);
|
|
96
|
-
if (await getVersion() === "0.31.0") return getEmptyResult();
|
|
97
|
-
return {
|
|
98
|
-
operations: createMongoMigrationOperations(options.updateSettings === false ? void 0 : {
|
|
99
|
-
type: "custom",
|
|
100
|
-
key: "version",
|
|
101
|
-
value: HOT_UPDATER_SCHEMA_VERSION
|
|
102
|
-
}),
|
|
103
|
-
execute: async () => {
|
|
104
|
-
const db = client.db();
|
|
105
|
-
for (const table of hotUpdaterSchema.tables) {
|
|
106
|
-
if (table.internal) continue;
|
|
107
|
-
await db.createCollection(table.ormName).catch(ignoreExistingCollection);
|
|
108
|
-
}
|
|
109
|
-
await db.collection("bundles").createIndex({ id: 1 }, { name: "bundles_id_idx" });
|
|
110
|
-
for (const table of hotUpdaterSchema.tables) {
|
|
111
|
-
if (table.internal) continue;
|
|
112
|
-
for (const index of (table.indexes ?? []).filter((item) => schemaIndexAppliesToProvider(item, "mongodb"))) await db.collection(table.ormName).createIndex(Object.fromEntries(index.columns.map((column) => [column, 1])), { name: index.name });
|
|
113
|
-
}
|
|
114
|
-
if (options.updateSettings !== false) await settings.updateOne({ key: "version" }, { $set: { value: HOT_UPDATER_SCHEMA_VERSION } }, { upsert: true });
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
};
|
|
118
|
-
return {
|
|
119
|
-
getVersion,
|
|
120
|
-
getNameVariants: async () => void 0,
|
|
121
|
-
next: async () => await getVersion() === "0.31.0" ? void 0 : { version: HOT_UPDATER_SCHEMA_VERSION },
|
|
122
65
|
previous: async () => void 0,
|
|
123
66
|
up: makeResult,
|
|
124
67
|
down: async () => {
|
|
125
68
|
throw new Error("No previous schema to migrate to.");
|
|
126
69
|
},
|
|
127
70
|
migrateTo: async (version, options) => {
|
|
128
|
-
if (version !== "0.
|
|
71
|
+
if (version !== "1.0.0") throw new Error(`Invalid version ${version}`);
|
|
129
72
|
return makeResult(options);
|
|
130
73
|
},
|
|
131
74
|
migrateToLatest: makeResult
|
|
132
75
|
};
|
|
133
76
|
};
|
|
134
77
|
//#endregion
|
|
135
|
-
export { createKyselyMigrator
|
|
78
|
+
export { createKyselyMigrator };
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
const require_types = require("../schema/types.cjs");
|
|
2
|
+
const require_fixedMigratorShared = require("./fixedMigratorShared.cjs");
|
|
3
|
+
const require_registry = require("./schema/registry.cjs");
|
|
4
|
+
const require_mongoMigrationExecution = require("./mongoMigrationExecution.cjs");
|
|
5
|
+
const require_mongodb = require("./schema/mongodb.cjs");
|
|
6
|
+
//#region src/db/fixedMigratorMongo.ts
|
|
7
|
+
const isMongoNamespaceExistsError = (error) => {
|
|
8
|
+
if (!(error instanceof Error)) return false;
|
|
9
|
+
const mongoError = error;
|
|
10
|
+
return mongoError.code === 48 || mongoError.codeName === "NamespaceExists";
|
|
11
|
+
};
|
|
12
|
+
const isMongoNamespaceNotFoundError = (error) => {
|
|
13
|
+
if (!(error instanceof Error)) return false;
|
|
14
|
+
const mongoError = error;
|
|
15
|
+
return mongoError.code === 26 || mongoError.codeName === "NamespaceNotFound";
|
|
16
|
+
};
|
|
17
|
+
const ignoreExistingCollection = (error) => {
|
|
18
|
+
if (isMongoNamespaceExistsError(error)) return;
|
|
19
|
+
throw error;
|
|
20
|
+
};
|
|
21
|
+
const mongoNullableString = { bsonType: ["string", "null"] };
|
|
22
|
+
const mongoByteSize = {
|
|
23
|
+
bsonType: [
|
|
24
|
+
"double",
|
|
25
|
+
"int",
|
|
26
|
+
"long"
|
|
27
|
+
],
|
|
28
|
+
maximum: Number.MAX_SAFE_INTEGER,
|
|
29
|
+
minimum: 0
|
|
30
|
+
};
|
|
31
|
+
const mongoBundleValidator = { $and: [{ $jsonSchema: {
|
|
32
|
+
bsonType: "object",
|
|
33
|
+
properties: {
|
|
34
|
+
archive_byte_size: mongoByteSize,
|
|
35
|
+
asset_base_storage_uri: mongoNullableString,
|
|
36
|
+
file_hash: { bsonType: "string" },
|
|
37
|
+
git_commit_hash: mongoNullableString,
|
|
38
|
+
id: { bsonType: "string" },
|
|
39
|
+
manifest_file_hash: mongoNullableString,
|
|
40
|
+
manifest_storage_uri: mongoNullableString,
|
|
41
|
+
metadata: { bsonType: "object" },
|
|
42
|
+
platform: { enum: ["ios", "android"] },
|
|
43
|
+
storage_uri: { bsonType: "string" }
|
|
44
|
+
},
|
|
45
|
+
required: [
|
|
46
|
+
"id",
|
|
47
|
+
"platform",
|
|
48
|
+
"file_hash",
|
|
49
|
+
"git_commit_hash",
|
|
50
|
+
"storage_uri",
|
|
51
|
+
"archive_byte_size",
|
|
52
|
+
"metadata",
|
|
53
|
+
"manifest_storage_uri",
|
|
54
|
+
"manifest_file_hash",
|
|
55
|
+
"asset_base_storage_uri"
|
|
56
|
+
]
|
|
57
|
+
} }, { $expr: { $eq: [{ $trunc: "$archive_byte_size" }, "$archive_byte_size"] } }] };
|
|
58
|
+
const mongoPatchValidator = { $and: [{ $jsonSchema: {
|
|
59
|
+
bsonType: "object",
|
|
60
|
+
properties: {
|
|
61
|
+
base_bundle_id: { bsonType: "string" },
|
|
62
|
+
base_file_hash: { bsonType: "string" },
|
|
63
|
+
bundle_id: { bsonType: "string" },
|
|
64
|
+
id: { bsonType: "string" },
|
|
65
|
+
order_index: mongoByteSize,
|
|
66
|
+
byte_size: mongoByteSize,
|
|
67
|
+
patch_file_hash: { bsonType: "string" },
|
|
68
|
+
patch_storage_uri: { bsonType: "string" }
|
|
69
|
+
},
|
|
70
|
+
required: [
|
|
71
|
+
"id",
|
|
72
|
+
"bundle_id",
|
|
73
|
+
"base_bundle_id",
|
|
74
|
+
"base_file_hash",
|
|
75
|
+
"patch_file_hash",
|
|
76
|
+
"patch_storage_uri",
|
|
77
|
+
"byte_size",
|
|
78
|
+
"order_index"
|
|
79
|
+
]
|
|
80
|
+
} }, { $expr: { $and: [{ $eq: [{ $trunc: "$order_index" }, "$order_index"] }, { $eq: [{ $trunc: "$byte_size" }, "$byte_size"] }] } }] };
|
|
81
|
+
const mongoReleaseValidator = { $jsonSchema: {
|
|
82
|
+
bsonType: "object",
|
|
83
|
+
properties: {
|
|
84
|
+
bundle_id: mongoNullableString,
|
|
85
|
+
channel_id: { bsonType: "string" },
|
|
86
|
+
created_at_ms: { bsonType: [
|
|
87
|
+
"double",
|
|
88
|
+
"int",
|
|
89
|
+
"long"
|
|
90
|
+
] },
|
|
91
|
+
enabled: { bsonType: "bool" },
|
|
92
|
+
fingerprint_hash: mongoNullableString,
|
|
93
|
+
id: { bsonType: "string" },
|
|
94
|
+
kind: { enum: ["BUNDLE", "EMBEDDED"] },
|
|
95
|
+
message: mongoNullableString,
|
|
96
|
+
operation: { enum: [
|
|
97
|
+
"DEPLOY",
|
|
98
|
+
"PROMOTE",
|
|
99
|
+
"ROLLBACK"
|
|
100
|
+
] },
|
|
101
|
+
platform: { enum: ["ios", "android"] },
|
|
102
|
+
revision: { bsonType: ["int", "long"] },
|
|
103
|
+
rollout_cohort_count: { bsonType: ["int", "long"] },
|
|
104
|
+
scope_key: { bsonType: "string" },
|
|
105
|
+
should_force_update: { bsonType: "bool" },
|
|
106
|
+
source_release_id: mongoNullableString,
|
|
107
|
+
strategy: { enum: ["APP_VERSION", "FINGERPRINT"] },
|
|
108
|
+
target_app_version: mongoNullableString,
|
|
109
|
+
target_cohorts: {
|
|
110
|
+
bsonType: "array",
|
|
111
|
+
items: { bsonType: "string" }
|
|
112
|
+
},
|
|
113
|
+
updated_at_ms: { bsonType: [
|
|
114
|
+
"double",
|
|
115
|
+
"int",
|
|
116
|
+
"long"
|
|
117
|
+
] }
|
|
118
|
+
},
|
|
119
|
+
required: [
|
|
120
|
+
"id",
|
|
121
|
+
"revision",
|
|
122
|
+
"scope_key",
|
|
123
|
+
"channel_id",
|
|
124
|
+
"platform",
|
|
125
|
+
"kind",
|
|
126
|
+
"bundle_id",
|
|
127
|
+
"strategy",
|
|
128
|
+
"target_app_version",
|
|
129
|
+
"fingerprint_hash",
|
|
130
|
+
"enabled",
|
|
131
|
+
"should_force_update",
|
|
132
|
+
"message",
|
|
133
|
+
"rollout_cohort_count",
|
|
134
|
+
"target_cohorts",
|
|
135
|
+
"operation",
|
|
136
|
+
"source_release_id",
|
|
137
|
+
"created_at_ms",
|
|
138
|
+
"updated_at_ms"
|
|
139
|
+
]
|
|
140
|
+
} };
|
|
141
|
+
const mongoReleaseCatalogValidator = { $jsonSchema: {
|
|
142
|
+
bsonType: "object",
|
|
143
|
+
properties: {
|
|
144
|
+
catalog_id: { bsonType: "string" },
|
|
145
|
+
byte_size: { bsonType: ["int", "long"] },
|
|
146
|
+
catalog_hash: { bsonType: "string" },
|
|
147
|
+
channel_id: { bsonType: "string" },
|
|
148
|
+
channel_key: { bsonType: "string" },
|
|
149
|
+
fingerprint_hash: mongoNullableString,
|
|
150
|
+
generation: { bsonType: [
|
|
151
|
+
"double",
|
|
152
|
+
"int",
|
|
153
|
+
"long"
|
|
154
|
+
] },
|
|
155
|
+
is_tombstone: { bsonType: "bool" },
|
|
156
|
+
payload: { bsonType: "string" },
|
|
157
|
+
platform: { enum: ["ios", "android"] },
|
|
158
|
+
scope_key: { bsonType: "string" },
|
|
159
|
+
strategy: { enum: ["APP_VERSION", "FINGERPRINT"] },
|
|
160
|
+
updated_at_ms: { bsonType: [
|
|
161
|
+
"double",
|
|
162
|
+
"int",
|
|
163
|
+
"long"
|
|
164
|
+
] }
|
|
165
|
+
},
|
|
166
|
+
required: [
|
|
167
|
+
"scope_key",
|
|
168
|
+
"catalog_id",
|
|
169
|
+
"strategy",
|
|
170
|
+
"channel_id",
|
|
171
|
+
"channel_key",
|
|
172
|
+
"platform",
|
|
173
|
+
"fingerprint_hash",
|
|
174
|
+
"generation",
|
|
175
|
+
"payload",
|
|
176
|
+
"catalog_hash",
|
|
177
|
+
"byte_size",
|
|
178
|
+
"is_tombstone",
|
|
179
|
+
"updated_at_ms"
|
|
180
|
+
]
|
|
181
|
+
} };
|
|
182
|
+
const createSettingsKeyIndexOperation = () => ({
|
|
183
|
+
description: `Ensure unique MongoDB index: ${require_types.HOT_UPDATER_SETTINGS_TABLE}(key)`,
|
|
184
|
+
type: "custom"
|
|
185
|
+
});
|
|
186
|
+
const createMongoMigrator = (client) => {
|
|
187
|
+
const settings = client.db().collection(require_types.HOT_UPDATER_SETTINGS_TABLE);
|
|
188
|
+
const getSetting = async (key) => {
|
|
189
|
+
const [row, duplicate] = await settings.find({ key }).limit(2).toArray();
|
|
190
|
+
if (!row) return void 0;
|
|
191
|
+
if (duplicate) throw new Error(`Duplicate Hot Updater schema setting: ${key}`);
|
|
192
|
+
if (typeof row.value !== "string") throw new Error(`Invalid Hot Updater schema setting: ${key}`);
|
|
193
|
+
return row.value;
|
|
194
|
+
};
|
|
195
|
+
const getCoreVersion = () => getSetting(require_types.HOT_UPDATER_CORE_SCHEMA_KEY);
|
|
196
|
+
const getSchemaVersions = async () => {
|
|
197
|
+
return {
|
|
198
|
+
coreVersion: await getCoreVersion(),
|
|
199
|
+
legacyCoreVersion: require_fixedMigratorShared.inferLegacyCoreSchemaVersion(await getSetting("version"))
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
const getVersion = async () => {
|
|
203
|
+
const { coreVersion, legacyCoreVersion } = await getSchemaVersions();
|
|
204
|
+
return coreVersion ?? legacyCoreVersion;
|
|
205
|
+
};
|
|
206
|
+
const getSettingsKeyIndexState = async () => {
|
|
207
|
+
const index = (await settings.listIndexes().toArray().catch((error) => {
|
|
208
|
+
if (isMongoNamespaceNotFoundError(error)) return [];
|
|
209
|
+
throw error;
|
|
210
|
+
})).find(({ key }) => {
|
|
211
|
+
const fields = Object.entries(key);
|
|
212
|
+
return fields.length === 1 && fields[0]?.[0] === "key" && fields[0][1] === 1;
|
|
213
|
+
});
|
|
214
|
+
if (!index) return "missing";
|
|
215
|
+
return index.unique === true && index.sparse !== true && index.partialFilterExpression === void 0 ? "unique" : "non-unique";
|
|
216
|
+
};
|
|
217
|
+
const rejectNonUniqueSettingsKeyIndex = () => {
|
|
218
|
+
throw new Error("Hot Updater settings key index must enforce uniqueness for every key.");
|
|
219
|
+
};
|
|
220
|
+
const ensureSettingsKeyIndex = async () => {
|
|
221
|
+
const state = await getSettingsKeyIndexState();
|
|
222
|
+
if (state === "unique") return;
|
|
223
|
+
if (state === "non-unique") rejectNonUniqueSettingsKeyIndex();
|
|
224
|
+
await settings.createIndex({ key: 1 }, { unique: true });
|
|
225
|
+
};
|
|
226
|
+
const makeResult = async (options = {}) => {
|
|
227
|
+
require_fixedMigratorShared.assertSupportedMigrationMode(options);
|
|
228
|
+
const { coreVersion, legacyCoreVersion } = await getSchemaVersions();
|
|
229
|
+
const settingsKeyIndexState = await getSettingsKeyIndexState();
|
|
230
|
+
if (settingsKeyIndexState === "non-unique") rejectNonUniqueSettingsKeyIndex();
|
|
231
|
+
if (require_fixedMigratorShared.isCurrentSchemaVersion(coreVersion)) {
|
|
232
|
+
if (settingsKeyIndexState === "unique") return require_fixedMigratorShared.getEmptyMigrationResult();
|
|
233
|
+
return {
|
|
234
|
+
...require_fixedMigratorShared.getEmptyMigrationResult(),
|
|
235
|
+
execute: ensureSettingsKeyIndex,
|
|
236
|
+
operations: [createSettingsKeyIndexOperation()]
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
require_fixedMigratorShared.assertCurrentOrEmptySchemaVersion(coreVersion ?? legacyCoreVersion);
|
|
240
|
+
const settingsOperation = options.updateSettings === false ? void 0 : {
|
|
241
|
+
type: "custom",
|
|
242
|
+
key: require_types.HOT_UPDATER_CORE_SCHEMA_KEY,
|
|
243
|
+
value: require_types.HOT_UPDATER_SCHEMA_VERSION
|
|
244
|
+
};
|
|
245
|
+
return {
|
|
246
|
+
operations: [createSettingsKeyIndexOperation(), ...require_mongodb.createMongoMigrationOperations(settingsOperation)],
|
|
247
|
+
execute: async () => {
|
|
248
|
+
const db = client.db();
|
|
249
|
+
await require_mongoMigrationExecution.executeMongoMigration({
|
|
250
|
+
updateSettings: options.updateSettings !== false,
|
|
251
|
+
backend: {
|
|
252
|
+
ensureCollections: async () => {
|
|
253
|
+
for (const table of require_registry.hotUpdaterSchema.tables) {
|
|
254
|
+
if (table.internal) continue;
|
|
255
|
+
await db.createCollection(table.ormName).catch(ignoreExistingCollection);
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
ensureIndexes: async () => {
|
|
259
|
+
await ensureSettingsKeyIndex();
|
|
260
|
+
for (const table of require_registry.hotUpdaterSchema.tables) {
|
|
261
|
+
if (table.internal) continue;
|
|
262
|
+
const collection = db.collection(table.ormName);
|
|
263
|
+
const primaryKey = table.columns.find((column) => column.primaryKey);
|
|
264
|
+
if (!primaryKey) throw new Error(`MongoDB table ${table.ormName} does not define a primary key.`);
|
|
265
|
+
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
|
+
await collection.createIndex({ [primaryKey.ormName]: 1 }, {
|
|
269
|
+
name: idIndexName,
|
|
270
|
+
unique: true
|
|
271
|
+
});
|
|
272
|
+
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
|
+
name: index.name,
|
|
274
|
+
...index.unique ? { unique: true } : {}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
enforceSchema: async () => {
|
|
279
|
+
for (const [collection, validator] of [
|
|
280
|
+
["bundles", mongoBundleValidator],
|
|
281
|
+
["bundle_patches", mongoPatchValidator],
|
|
282
|
+
["releases", mongoReleaseValidator],
|
|
283
|
+
["release_catalogs", mongoReleaseCatalogValidator]
|
|
284
|
+
]) await db.command({
|
|
285
|
+
collMod: collection,
|
|
286
|
+
validationAction: "error",
|
|
287
|
+
validationLevel: "strict",
|
|
288
|
+
validator
|
|
289
|
+
});
|
|
290
|
+
},
|
|
291
|
+
updateVersion: async () => {
|
|
292
|
+
await settings.updateOne({ key: require_types.HOT_UPDATER_CORE_SCHEMA_KEY }, { $set: { value: require_types.HOT_UPDATER_SCHEMA_VERSION } }, { upsert: true });
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
};
|
|
299
|
+
return {
|
|
300
|
+
getVersion,
|
|
301
|
+
getNameVariants: async () => void 0,
|
|
302
|
+
next: async () => {
|
|
303
|
+
const { coreVersion } = await getSchemaVersions();
|
|
304
|
+
return require_fixedMigratorShared.isCurrentSchemaVersion(coreVersion) ? void 0 : { version: require_types.HOT_UPDATER_SCHEMA_VERSION };
|
|
305
|
+
},
|
|
306
|
+
previous: async () => void 0,
|
|
307
|
+
up: makeResult,
|
|
308
|
+
down: async () => {
|
|
309
|
+
throw new Error("No previous schema to migrate to.");
|
|
310
|
+
},
|
|
311
|
+
migrateTo: async (version, options) => {
|
|
312
|
+
if (version !== "1.0.0") throw new Error(`Invalid version ${version}`);
|
|
313
|
+
return makeResult(options);
|
|
314
|
+
},
|
|
315
|
+
migrateToLatest: makeResult
|
|
316
|
+
};
|
|
317
|
+
};
|
|
318
|
+
//#endregion
|
|
319
|
+
exports.createMongoMigrator = createMongoMigrator;
|