@hot-updater/server 1.0.0-rc.2 → 1.0.0-rc.21
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/LICENSE +12 -14
- package/dist/adapters/drizzle.cjs +32 -75
- package/dist/adapters/drizzle.d.cts +13 -5
- package/dist/adapters/drizzle.d.mts +13 -5
- package/dist/adapters/drizzle.mjs +32 -77
- package/dist/adapters/drizzleExecutor.cjs +114 -0
- package/dist/adapters/drizzleExecutor.d.cts +9 -0
- package/dist/adapters/drizzleExecutor.d.mts +9 -0
- package/dist/adapters/drizzleExecutor.mjs +112 -0
- package/dist/adapters/kysely.cjs +22 -31
- package/dist/adapters/kysely.d.cts +10 -6
- package/dist/adapters/kysely.d.mts +10 -6
- package/dist/adapters/kysely.mjs +23 -33
- package/dist/adapters/kyselyExecutor.cjs +32 -0
- package/dist/adapters/kyselyExecutor.d.cts +11 -0
- package/dist/adapters/kyselyExecutor.d.mts +11 -0
- package/dist/adapters/kyselyExecutor.mjs +32 -0
- package/dist/adapters/mongodb.cjs +18 -54
- package/dist/adapters/mongodb.d.cts +10 -5
- package/dist/adapters/mongodb.d.mts +10 -5
- package/dist/adapters/mongodb.mjs +19 -56
- package/dist/adapters/mongodbAdapter.cjs +192 -0
- package/dist/adapters/mongodbAdapter.d.cts +9 -0
- package/dist/adapters/mongodbAdapter.d.mts +9 -0
- package/dist/adapters/mongodbAdapter.mjs +191 -0
- package/dist/adapters/prisma.cjs +35 -267
- package/dist/adapters/prisma.d.cts +12 -7
- package/dist/adapters/prisma.d.mts +12 -7
- package/dist/adapters/prisma.mjs +36 -268
- package/dist/adapters/prismaExecutor.cjs +63 -0
- package/dist/adapters/prismaExecutor.mjs +63 -0
- package/dist/adapters/sqlProviders.cjs +14 -0
- package/dist/adapters/sqlProviders.mjs +14 -0
- package/dist/assembly/assemblePlugins.cjs +144 -0
- package/dist/assembly/assemblePlugins.d.cts +5 -0
- package/dist/assembly/assemblePlugins.d.mts +5 -0
- package/dist/assembly/assemblePlugins.mjs +139 -0
- package/dist/assembly/clientPlugins.cjs +88 -0
- package/dist/assembly/clientPlugins.mjs +88 -0
- package/dist/assembly/configError.d.cts +2 -0
- package/dist/assembly/configError.d.mts +2 -0
- package/dist/assembly/configError.mjs +2 -0
- package/dist/core/api.cjs +51 -0
- package/dist/core/api.d.cts +54 -0
- package/dist/core/api.d.mts +54 -0
- package/dist/core/api.mjs +51 -0
- package/dist/core/baseCandidates.cjs +28 -0
- package/dist/core/baseCandidates.mjs +28 -0
- package/dist/core/operations.cjs +351 -0
- package/dist/core/operations.mjs +351 -0
- package/dist/core/reads.cjs +273 -0
- package/dist/core/reads.d.cts +9 -0
- package/dist/core/reads.d.mts +9 -0
- package/dist/core/reads.mjs +267 -0
- package/dist/core/releases.cjs +193 -0
- package/dist/core/releases.mjs +190 -0
- package/dist/core/writes.cjs +96 -0
- package/dist/core/writes.mjs +91 -0
- package/dist/createHotUpdaterCore.cjs +72 -91
- package/dist/createHotUpdaterCore.d.cts +106 -38
- package/dist/createHotUpdaterCore.d.mts +106 -38
- package/dist/createHotUpdaterCore.mjs +74 -89
- package/dist/db/engineDrizzleSchema.cjs +53 -0
- package/dist/db/engineDrizzleSchema.mjs +53 -0
- package/dist/db/enginePrismaSchema.cjs +84 -0
- package/dist/db/enginePrismaSchema.d.cts +5 -0
- package/dist/db/enginePrismaSchema.d.mts +5 -0
- package/dist/db/enginePrismaSchema.mjs +83 -0
- package/dist/db/releaseCatalog.cjs +24 -47
- package/dist/db/releaseCatalog.mjs +20 -44
- package/dist/db/updateArtifacts.cjs +43 -72
- package/dist/db/updateArtifacts.mjs +40 -69
- package/dist/handler.cjs +59 -43
- package/dist/handler.d.cts +3 -5
- package/dist/handler.d.mts +3 -5
- package/dist/handler.mjs +61 -43
- package/dist/handlerAdminRoutes.cjs +374 -0
- package/dist/handlerAdminRoutes.mjs +372 -0
- package/dist/handlerParameters.cjs +6 -11
- package/dist/handlerParameters.mjs +6 -10
- package/dist/handlerReleaseCatalogRoutes.cjs +32 -15
- package/dist/handlerReleaseCatalogRoutes.mjs +32 -15
- package/dist/handlerTypes.d.cts +2 -55
- package/dist/handlerTypes.d.mts +2 -55
- package/dist/handlerVersionRoutes.cjs +20 -4
- package/dist/handlerVersionRoutes.mjs +20 -4
- package/dist/index.cjs +9 -9
- package/dist/index.d.cts +8 -9
- package/dist/index.d.mts +8 -9
- package/dist/index.mjs +3 -4
- package/dist/node.cjs +3 -6
- package/dist/node.d.cts +2 -2
- package/dist/node.d.mts +2 -2
- package/dist/node.mjs +4 -4
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/plugins/api-keys/index.cjs +9 -0
- package/dist/plugins/api-keys/index.d.cts +1 -0
- package/dist/plugins/api-keys/index.d.mts +1 -0
- package/dist/plugins/api-keys/index.mjs +2 -0
- package/dist/plugins/definePlugin.d.cts +2 -0
- package/dist/plugins/definePlugin.d.mts +2 -0
- package/dist/plugins/insights/index.cjs +9 -0
- package/dist/plugins/insights/index.d.cts +1 -0
- package/dist/plugins/insights/index.d.mts +1 -0
- package/dist/plugins/insights/index.mjs +2 -0
- package/dist/plugins/official.cjs +30 -0
- package/dist/plugins/official.mjs +29 -0
- package/dist/storageAccess.cjs +13 -10
- package/dist/storageAccess.mjs +13 -10
- package/dist/types/index.d.cts +2 -28
- package/dist/types/index.d.mts +2 -28
- package/package.json +26 -14
- package/dist/_virtual/_rolldown/runtime.cjs +0 -23
- package/dist/adapters/databaseConstraintErrors.cjs +0 -22
- package/dist/adapters/databaseConstraintErrors.mjs +0 -21
- package/dist/adapters/databasePluginUtils.cjs +0 -116
- package/dist/adapters/databasePluginUtils.mjs +0 -106
- package/dist/adapters/drizzleCrud.cjs +0 -311
- package/dist/adapters/drizzleCrud.mjs +0 -308
- package/dist/adapters/drizzleLazyDB.cjs +0 -106
- package/dist/adapters/drizzleLazyDB.mjs +0 -106
- package/dist/adapters/drizzleQuery.cjs +0 -69
- package/dist/adapters/drizzleQuery.mjs +0 -69
- package/dist/adapters/insightsTransaction.cjs +0 -22
- package/dist/adapters/insightsTransaction.mjs +0 -22
- package/dist/adapters/kyselyCrud.cjs +0 -305
- package/dist/adapters/kyselyCrud.mjs +0 -304
- package/dist/adapters/kyselyQuery.cjs +0 -56
- package/dist/adapters/kyselyQuery.mjs +0 -56
- package/dist/adapters/mongodbCollections.cjs +0 -38
- package/dist/adapters/mongodbCollections.mjs +0 -32
- package/dist/adapters/mongodbQuery.cjs +0 -94
- package/dist/adapters/mongodbQuery.mjs +0 -86
- package/dist/adapters/mongodbReads.cjs +0 -210
- package/dist/adapters/mongodbReads.mjs +0 -210
- package/dist/adapters/mongodbWrites.cjs +0 -148
- package/dist/adapters/mongodbWrites.mjs +0 -148
- package/dist/adapters/prismaQuery.cjs +0 -57
- package/dist/adapters/prismaQuery.mjs +0 -56
- package/dist/adapters/prismaRows.cjs +0 -219
- package/dist/adapters/prismaRows.mjs +0 -209
- package/dist/apiKeys.cjs +0 -143
- package/dist/apiKeys.d.cts +0 -49
- package/dist/apiKeys.d.mts +0 -49
- package/dist/apiKeys.mjs +0 -133
- package/dist/db/createBundleDiff.cjs +0 -144
- package/dist/db/createBundleDiff.d.cts +0 -16
- package/dist/db/createBundleDiff.d.mts +0 -16
- package/dist/db/createBundleDiff.mjs +0 -141
- package/dist/db/databasePluginCore.cjs +0 -137
- package/dist/db/databasePluginCore.mjs +0 -137
- package/dist/db/fixedMigrator.cjs +0 -79
- package/dist/db/fixedMigrator.mjs +0 -78
- package/dist/db/fixedMigratorMongo.cjs +0 -321
- package/dist/db/fixedMigratorMongo.mjs +0 -321
- package/dist/db/fixedMigratorShared.cjs +0 -23
- package/dist/db/fixedMigratorShared.mjs +0 -18
- package/dist/db/index.cjs +0 -27
- package/dist/db/index.d.cts +0 -12
- package/dist/db/index.d.mts +0 -12
- package/dist/db/index.mjs +0 -22
- package/dist/db/mongoMigrationExecution.cjs +0 -11
- package/dist/db/mongoMigrationExecution.mjs +0 -11
- package/dist/db/releaseCatalog.d.cts +0 -16
- package/dist/db/releaseCatalog.d.mts +0 -16
- package/dist/db/schema/insightsCollation.cjs +0 -14
- package/dist/db/schema/insightsCollation.mjs +0 -14
- package/dist/db/schema/mongodb.cjs +0 -25
- package/dist/db/schema/mongodb.mjs +0 -25
- package/dist/db/schema/registry.cjs +0 -21
- package/dist/db/schema/registry.mjs +0 -17
- package/dist/db/schema/sql.cjs +0 -105
- package/dist/db/schema/sql.mjs +0 -97
- package/dist/db/schema/sqlOperations.cjs +0 -27
- package/dist/db/schema/sqlOperations.mjs +0 -26
- package/dist/db/schemaGenerators.cjs +0 -275
- package/dist/db/schemaGenerators.mjs +0 -273
- package/dist/db/schemaReadiness.cjs +0 -26
- package/dist/db/schemaReadiness.d.cts +0 -9
- package/dist/db/schemaReadiness.d.mts +0 -9
- package/dist/db/schemaReadiness.mjs +0 -25
- package/dist/db/sqlMigrationExecution.cjs +0 -67
- package/dist/db/sqlMigrationExecution.mjs +0 -67
- package/dist/db/types.cjs +0 -22
- package/dist/db/types.d.cts +0 -118
- package/dist/db/types.d.mts +0 -118
- package/dist/db/types.mjs +0 -19
- package/dist/handlerBundleRoutes.cjs +0 -155
- package/dist/handlerBundleRoutes.mjs +0 -155
- package/dist/handlerReleaseManagementRoutes.cjs +0 -124
- package/dist/handlerReleaseManagementRoutes.mjs +0 -124
- package/dist/insights/domain.d.cts +0 -89
- package/dist/insights/domain.d.mts +0 -89
- package/dist/insights/errors.cjs +0 -15
- package/dist/insights/errors.mjs +0 -14
- package/dist/insights/eventInput.cjs +0 -155
- package/dist/insights/eventInput.mjs +0 -153
- package/dist/insights/provider.cjs +0 -314
- package/dist/insights/provider.d.cts +0 -6
- package/dist/insights/provider.d.mts +0 -6
- package/dist/insights/provider.mjs +0 -314
- package/dist/insights/queryInput.cjs +0 -93
- package/dist/insights/queryInput.mjs +0 -91
- package/dist/insights/routes.cjs +0 -58
- package/dist/insights/routes.mjs +0 -56
- package/dist/insights/types.d.cts +0 -32
- package/dist/insights/types.d.mts +0 -32
- package/dist/schema/dsl.cjs +0 -103
- package/dist/schema/dsl.mjs +0 -87
- package/dist/schema/index.cjs +0 -20
- package/dist/schema/index.mjs +0 -7
- package/dist/schema/settings.cjs +0 -9
- package/dist/schema/settings.mjs +0 -9
- package/dist/schema/types.cjs +0 -8
- package/dist/schema/types.mjs +0 -6
- package/dist/schema/v1_0_0.cjs +0 -406
- package/dist/schema/v1_0_0.mjs +0 -398
- package/src/adapters/databaseConstraintErrors.ts +0 -25
- package/src/adapters/databasePluginTestDatabase.ts +0 -120
- package/src/adapters/databasePluginUtils.spec.ts +0 -29
- package/src/adapters/databasePluginUtils.ts +0 -214
- package/src/adapters/drizzle.spec.ts +0 -336
- package/src/adapters/drizzle.ts +0 -162
- package/src/adapters/drizzleCrud.ts +0 -571
- package/src/adapters/drizzleLazyDB.ts +0 -271
- package/src/adapters/drizzleQuery.ts +0 -164
- package/src/adapters/insightsTransaction.ts +0 -32
- package/src/adapters/kysely.spec.ts +0 -174
- package/src/adapters/kysely.ts +0 -110
- package/src/adapters/kyselyCrud.ts +0 -709
- package/src/adapters/kyselyQuery.ts +0 -128
- package/src/adapters/mongodb.integration.spec.ts +0 -210
- package/src/adapters/mongodb.spec.ts +0 -209
- package/src/adapters/mongodb.ts +0 -138
- package/src/adapters/mongodbCollections.ts +0 -67
- package/src/adapters/mongodbQuery.ts +0 -255
- package/src/adapters/mongodbReads.ts +0 -380
- package/src/adapters/mongodbRows.spec.ts +0 -64
- package/src/adapters/mongodbRows.ts +0 -118
- package/src/adapters/mongodbTestClient.ts +0 -377
- package/src/adapters/mongodbTestFilter.ts +0 -169
- package/src/adapters/mongodbWrites.ts +0 -287
- package/src/adapters/prisma.spec.ts +0 -293
- package/src/adapters/prisma.ts +0 -565
- package/src/adapters/prismaQuery.ts +0 -129
- package/src/adapters/prismaRows.spec.ts +0 -98
- package/src/adapters/prismaRows.ts +0 -337
- package/src/adapters/prismaTestClient.ts +0 -413
- package/src/apiKeys.integration.spec.ts +0 -192
- package/src/apiKeys.spec.ts +0 -162
- package/src/apiKeys.ts +0 -220
- package/src/calculatePagination.ts +0 -34
- package/src/createHotUpdaterCore.ts +0 -246
- package/src/db/bundleRows.spec.ts +0 -164
- package/src/db/bundleRows.ts +0 -10
- package/src/db/createBundleDiff.spec.ts +0 -450
- package/src/db/createBundleDiff.ts +0 -364
- package/src/db/databasePluginCore.spec.ts +0 -62
- package/src/db/databasePluginCore.testFixtures.ts +0 -76
- package/src/db/databasePluginCore.ts +0 -185
- package/src/db/databasePluginUpdateCheck.bench.ts +0 -110
- package/src/db/fixedMigrator.spec.ts +0 -296
- package/src/db/fixedMigrator.ts +0 -147
- package/src/db/fixedMigratorMongo.spec.ts +0 -239
- package/src/db/fixedMigratorMongo.ts +0 -425
- package/src/db/fixedMigratorShared.ts +0 -36
- package/src/db/hotUpdaterSchema.ts +0 -5
- package/src/db/index.spec.ts +0 -1269
- package/src/db/index.ts +0 -47
- package/src/db/mongoMigrationExecution.ts +0 -23
- package/src/db/node-sqlite.d.ts +0 -25
- package/src/db/releaseCatalog.ts +0 -148
- package/src/db/schema/definitions.ts +0 -1
- package/src/db/schema/insightsCollation.ts +0 -21
- package/src/db/schema/mongodb.ts +0 -40
- package/src/db/schema/registry.ts +0 -55
- package/src/db/schema/sql.ts +0 -244
- package/src/db/schema/sqlOperations.ts +0 -63
- package/src/db/schema/types.ts +0 -1
- package/src/db/schemaGenerators.ts +0 -494
- package/src/db/schemaReadiness.ts +0 -34
- package/src/db/sqlMigrationExecution.spec.ts +0 -65
- package/src/db/sqlMigrationExecution.ts +0 -108
- package/src/db/types.spec.ts +0 -63
- package/src/db/types.ts +0 -228
- package/src/db/updateArtifacts.spec.ts +0 -359
- package/src/db/updateArtifacts.ts +0 -541
- package/src/handler-standalone.integration.spec.ts +0 -528
- package/src/handler.spec.ts +0 -190
- package/src/handler.testFixtures.ts +0 -30
- package/src/handler.ts +0 -245
- package/src/handlerAuth.integration.spec.ts +0 -33
- package/src/handlerBundleRoutes.ts +0 -259
- package/src/handlerErrors.ts +0 -7
- package/src/handlerManagement.spec.ts +0 -262
- package/src/handlerParameters.ts +0 -105
- package/src/handlerReleaseCatalogRoutes.ts +0 -154
- package/src/handlerReleaseManagementRoutes.ts +0 -213
- package/src/handlerTypes.ts +0 -96
- package/src/handlerVersionRoutes.ts +0 -12
- package/src/index.ts +0 -30
- package/src/insights/domain.ts +0 -103
- package/src/insights/errors.ts +0 -11
- package/src/insights/eventInput.ts +0 -225
- package/src/insights/insights.integration.spec.ts +0 -381
- package/src/insights/provider.spec.ts +0 -385
- package/src/insights/provider.ts +0 -591
- package/src/insights/queryInput.ts +0 -141
- package/src/insights/routes.ts +0 -104
- package/src/insights/types.ts +0 -55
- package/src/internalRouter.ts +0 -104
- package/src/node.spec.ts +0 -119
- package/src/node.ts +0 -111
- package/src/releaseCatalogRoutes.integration.spec.ts +0 -238
- package/src/runtime.spec.ts +0 -194
- package/src/runtime.testFixtures.ts +0 -71
- package/src/schema/dsl-all-versions.spec.ts +0 -37
- package/src/schema/dsl.ts +0 -187
- package/src/schema/index.ts +0 -10
- package/src/schema/settings.ts +0 -15
- package/src/schema/types.ts +0 -79
- package/src/schema/v1_0_0.spec.ts +0 -220
- package/src/schema/v1_0_0.ts +0 -529
- package/src/storageAccess.spec.ts +0 -152
- package/src/storageAccess.ts +0 -141
- package/src/types/index.ts +0 -34
- package/src/version.ts +0 -3
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { kyselyExecutor } from "./kyselyExecutor.cjs";
|
|
2
|
+
import { SqlDialect, ToolingDatabase } from "@hot-updater/plugin-core";
|
|
2
3
|
import { Kysely } from "kysely";
|
|
3
4
|
//#region src/adapters/kysely.d.ts
|
|
4
|
-
type KyselySQLProvider = Exclude<ORMSQLProvider, "mssql">;
|
|
5
5
|
interface KyselyAdapterConfig<TDatabase extends object = object> {
|
|
6
6
|
readonly db: Kysely<TDatabase>;
|
|
7
|
-
readonly provider:
|
|
8
|
-
readonly relationMode?: RelationMode;
|
|
7
|
+
readonly provider: SqlDialect;
|
|
9
8
|
}
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Hot Updater's database on a Kysely instance: the storage engine through the
|
|
11
|
+
* shared SQL core, fenced by the schema settings. `db migrate` and
|
|
12
|
+
* `db generate --sql` apply the engine's SQL schema.
|
|
13
|
+
*/
|
|
14
|
+
declare const kyselyAdapter: <TDatabase extends object>(config: KyselyAdapterConfig<TDatabase>) => ToolingDatabase;
|
|
11
15
|
//#endregion
|
|
12
|
-
export { KyselyAdapterConfig, type
|
|
16
|
+
export { KyselyAdapterConfig, type SqlDialect as SQLProvider, kyselyAdapter, kyselyExecutor };
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { kyselyExecutor } from "./kyselyExecutor.mjs";
|
|
2
|
+
import { SqlDialect, ToolingDatabase } from "@hot-updater/plugin-core";
|
|
2
3
|
import { Kysely } from "kysely";
|
|
3
4
|
//#region src/adapters/kysely.d.ts
|
|
4
|
-
type KyselySQLProvider = Exclude<ORMSQLProvider, "mssql">;
|
|
5
5
|
interface KyselyAdapterConfig<TDatabase extends object = object> {
|
|
6
6
|
readonly db: Kysely<TDatabase>;
|
|
7
|
-
readonly provider:
|
|
8
|
-
readonly relationMode?: RelationMode;
|
|
7
|
+
readonly provider: SqlDialect;
|
|
9
8
|
}
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Hot Updater's database on a Kysely instance: the storage engine through the
|
|
11
|
+
* shared SQL core, fenced by the schema settings. `db migrate` and
|
|
12
|
+
* `db generate --sql` apply the engine's SQL schema.
|
|
13
|
+
*/
|
|
14
|
+
declare const kyselyAdapter: <TDatabase extends object>(config: KyselyAdapterConfig<TDatabase>) => ToolingDatabase;
|
|
11
15
|
//#endregion
|
|
12
|
-
export { KyselyAdapterConfig, type
|
|
16
|
+
export { KyselyAdapterConfig, type SqlDialect as SQLProvider, kyselyAdapter, kyselyExecutor };
|
package/dist/adapters/kysely.mjs
CHANGED
|
@@ -1,38 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { createDatabasePlugin } from "@hot-updater/plugin-core";
|
|
5
|
-
import { createDatabasePluginAdapter } from "@hot-updater/plugin-core/internal";
|
|
1
|
+
import { kyselyExecutor } from "./kyselyExecutor.mjs";
|
|
2
|
+
import { checkSqlProvider } from "./sqlProviders.mjs";
|
|
3
|
+
import { coreTarget, createEngineDatabase, createEngineSqlMigrator, createSqlAdapter } from "@hot-updater/plugin-core";
|
|
6
4
|
//#region src/adapters/kysely.ts
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
recordInsights: (input) => runInsightsTransaction(() => db.transaction().execute((transaction) => recordKyselyInsights(transaction, config.provider, input))),
|
|
13
|
-
deleteChannel: (input) => db.transaction().execute((transaction) => createKyselyCrud(transaction, config.provider, relationMode).deleteChannel(input)),
|
|
14
|
-
create: (input) => db.transaction().execute((transaction) => createKyselyCrud(transaction, config.provider, relationMode).create(input)),
|
|
15
|
-
update: (input) => db.transaction().execute((transaction) => createKyselyCrud(transaction, config.provider, relationMode).update(input)),
|
|
16
|
-
delete: (input) => db.transaction().execute((transaction) => createKyselyCrud(transaction, config.provider, relationMode).delete(input)),
|
|
17
|
-
transaction: (callback) => db.transaction().execute((transaction) => callback(createKyselyCrud(transaction, config.provider, relationMode)))
|
|
18
|
-
};
|
|
19
|
-
};
|
|
5
|
+
/**
|
|
6
|
+
* Hot Updater's database on a Kysely instance: the storage engine through the
|
|
7
|
+
* shared SQL core, fenced by the schema settings. `db migrate` and
|
|
8
|
+
* `db generate --sql` apply the engine's SQL schema.
|
|
9
|
+
*/
|
|
20
10
|
const kyselyAdapter = (config) => {
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
11
|
+
const provider = checkSqlProvider("kyselyAdapter", config.provider);
|
|
12
|
+
const executor = kyselyExecutor(config.db, provider);
|
|
13
|
+
return {
|
|
14
|
+
...createEngineDatabase({
|
|
15
|
+
name: "kysely",
|
|
16
|
+
adapter: createSqlAdapter({ executor })
|
|
17
|
+
}),
|
|
18
|
+
provider,
|
|
19
|
+
createMigrator: ({ schema, settings } = coreTarget) => createEngineSqlMigrator({
|
|
20
|
+
adapterName: "kysely",
|
|
21
|
+
executor,
|
|
22
|
+
schema,
|
|
23
|
+
settings
|
|
34
24
|
})
|
|
35
|
-
}
|
|
25
|
+
};
|
|
36
26
|
};
|
|
37
27
|
//#endregion
|
|
38
|
-
export { kyselyAdapter };
|
|
28
|
+
export { kyselyAdapter, kyselyExecutor };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
let kysely = require("kysely");
|
|
2
|
+
//#region src/adapters/kyselyExecutor.ts
|
|
3
|
+
const over = (runner) => ({ async execute({ sql, params }) {
|
|
4
|
+
const result = await runner.executeQuery(kysely.CompiledQuery.raw(sql, [...params]));
|
|
5
|
+
return {
|
|
6
|
+
rows: result.rows,
|
|
7
|
+
changes: Number(result.numAffectedRows ?? 0n)
|
|
8
|
+
};
|
|
9
|
+
} });
|
|
10
|
+
const raw = (runner, sql) => runner.executeQuery(kysely.CompiledQuery.raw(sql));
|
|
11
|
+
/**
|
|
12
|
+
* The SQL core's executor over a Kysely instance: statements run as raw
|
|
13
|
+
* compiled queries. SQLite transactions begin with BEGIN IMMEDIATE on one
|
|
14
|
+
* connection; other dialects use Kysely's transactions.
|
|
15
|
+
*/
|
|
16
|
+
const kyselyExecutor = (db, dialect) => ({
|
|
17
|
+
dialect,
|
|
18
|
+
...over(db),
|
|
19
|
+
transaction: (fn) => dialect === "sqlite" ? db.connection().execute(async (connection) => {
|
|
20
|
+
await raw(connection, "BEGIN IMMEDIATE");
|
|
21
|
+
try {
|
|
22
|
+
const result = await fn(over(connection));
|
|
23
|
+
await raw(connection, "COMMIT");
|
|
24
|
+
return result;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
await raw(connection, "ROLLBACK").catch(() => void 0);
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}) : db.transaction().execute((transaction) => fn(over(transaction)))
|
|
30
|
+
});
|
|
31
|
+
//#endregion
|
|
32
|
+
exports.kyselyExecutor = kyselyExecutor;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SqlDialect, SqlExecutor } from "@hot-updater/plugin-core";
|
|
2
|
+
import { Kysely } from "kysely";
|
|
3
|
+
//#region src/adapters/kyselyExecutor.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The SQL core's executor over a Kysely instance: statements run as raw
|
|
6
|
+
* compiled queries. SQLite transactions begin with BEGIN IMMEDIATE on one
|
|
7
|
+
* connection; other dialects use Kysely's transactions.
|
|
8
|
+
*/
|
|
9
|
+
declare const kyselyExecutor: (db: Kysely<object>, dialect: SqlDialect) => SqlExecutor;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { kyselyExecutor };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SqlDialect, SqlExecutor } from "@hot-updater/plugin-core";
|
|
2
|
+
import { Kysely } from "kysely";
|
|
3
|
+
//#region src/adapters/kyselyExecutor.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The SQL core's executor over a Kysely instance: statements run as raw
|
|
6
|
+
* compiled queries. SQLite transactions begin with BEGIN IMMEDIATE on one
|
|
7
|
+
* connection; other dialects use Kysely's transactions.
|
|
8
|
+
*/
|
|
9
|
+
declare const kyselyExecutor: (db: Kysely<object>, dialect: SqlDialect) => SqlExecutor;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { kyselyExecutor };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { CompiledQuery } from "kysely";
|
|
2
|
+
//#region src/adapters/kyselyExecutor.ts
|
|
3
|
+
const over = (runner) => ({ async execute({ sql, params }) {
|
|
4
|
+
const result = await runner.executeQuery(CompiledQuery.raw(sql, [...params]));
|
|
5
|
+
return {
|
|
6
|
+
rows: result.rows,
|
|
7
|
+
changes: Number(result.numAffectedRows ?? 0n)
|
|
8
|
+
};
|
|
9
|
+
} });
|
|
10
|
+
const raw = (runner, sql) => runner.executeQuery(CompiledQuery.raw(sql));
|
|
11
|
+
/**
|
|
12
|
+
* The SQL core's executor over a Kysely instance: statements run as raw
|
|
13
|
+
* compiled queries. SQLite transactions begin with BEGIN IMMEDIATE on one
|
|
14
|
+
* connection; other dialects use Kysely's transactions.
|
|
15
|
+
*/
|
|
16
|
+
const kyselyExecutor = (db, dialect) => ({
|
|
17
|
+
dialect,
|
|
18
|
+
...over(db),
|
|
19
|
+
transaction: (fn) => dialect === "sqlite" ? db.connection().execute(async (connection) => {
|
|
20
|
+
await raw(connection, "BEGIN IMMEDIATE");
|
|
21
|
+
try {
|
|
22
|
+
const result = await fn(over(connection));
|
|
23
|
+
await raw(connection, "COMMIT");
|
|
24
|
+
return result;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
await raw(connection, "ROLLBACK").catch(() => void 0);
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}) : db.transaction().execute((transaction) => fn(over(transaction)))
|
|
30
|
+
});
|
|
31
|
+
//#endregion
|
|
32
|
+
export { kyselyExecutor };
|
|
@@ -1,61 +1,25 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
3
|
-
const require_mongodbCollections = require("./mongodbCollections.cjs");
|
|
4
|
-
const require_mongodbReads = require("./mongodbReads.cjs");
|
|
5
|
-
const require_mongodbWrites = require("./mongodbWrites.cjs");
|
|
2
|
+
const require_mongodbAdapter = require("./mongodbAdapter.cjs");
|
|
6
3
|
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
7
|
-
let _hot_updater_plugin_core_internal = require("@hot-updater/plugin-core/internal");
|
|
8
|
-
let mongodb = require("mongodb");
|
|
9
4
|
//#region src/adapters/mongodb.ts
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const record = () => client.withSession((recordSession) => recordSession.withTransaction(async () => {
|
|
15
|
-
const records = require_mongodbCollections.createMongoCollections(client);
|
|
16
|
-
const options = {
|
|
17
|
-
session: recordSession,
|
|
18
|
-
collation: { locale: "simple" }
|
|
19
|
-
};
|
|
20
|
-
if ((await records.bundleEvents.updateOne({ id: input.event.id }, { $setOnInsert: input.event }, {
|
|
21
|
-
...options,
|
|
22
|
-
upsert: true
|
|
23
|
-
})).upsertedCount === 0) return;
|
|
24
|
-
const current = await records.bundleInstallations.findOne({ install_id: input.installation.install_id }, options);
|
|
25
|
-
if (current === null) await records.bundleInstallations.insertOne({ ...input.installation }, { session: recordSession });
|
|
26
|
-
else if (input.installation.received_at_ms > current.received_at_ms || input.installation.received_at_ms === current.received_at_ms && (0, _hot_updater_plugin_core.compareInsightsText)(input.installation.id, current.id) > 0) await records.bundleInstallations.updateOne({ install_id: input.installation.install_id }, { $set: input.installation }, options);
|
|
27
|
-
}, {
|
|
28
|
-
readConcern: { level: "snapshot" },
|
|
29
|
-
readPreference: "primary",
|
|
30
|
-
writeConcern: { w: "majority" }
|
|
31
|
-
}));
|
|
32
|
-
try {
|
|
33
|
-
await record();
|
|
34
|
-
} catch (error) {
|
|
35
|
-
if (!(error instanceof mongodb.MongoServerError) || error.code !== 11e3) throw error;
|
|
36
|
-
await record();
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
...require_mongodbWrites.createMongoWrites(collections, session),
|
|
40
|
-
...require_mongodbReads.createMongoReads(collections, session)
|
|
41
|
-
};
|
|
5
|
+
/** Settings rows by their `key` field: the engine's rows and a v0 database's alike. */
|
|
6
|
+
const readSettings = (client) => async () => {
|
|
7
|
+
const rows = await client.db().collection(_hot_updater_plugin_core.SETTINGS_TABLE.name).find({ key: { $type: "string" } }).toArray();
|
|
8
|
+
return new Map(rows.map((row) => [String(row.key), row.value]));
|
|
42
9
|
};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const mongoAdapter = (config) => {
|
|
49
|
-
|
|
50
|
-
return Object.assign((0, _hot_updater_plugin_core.createDatabasePlugin)({
|
|
10
|
+
/**
|
|
11
|
+
* Hot Updater's database on MongoDB: the storage engine's MongoDB adapter,
|
|
12
|
+
* fenced by the schema settings. `db migrate` creates the collections and
|
|
13
|
+
* indexes, then writes the settings.
|
|
14
|
+
*/
|
|
15
|
+
const mongoAdapter = (config) => ({
|
|
16
|
+
...(0, _hot_updater_plugin_core.createEngineDatabase)({
|
|
51
17
|
name: "mongodb",
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}),
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
createMigrator: () => require_fixedMigratorMongo.createMongoMigrator(config.client)
|
|
58
|
-
});
|
|
59
|
-
};
|
|
18
|
+
adapter: require_mongodbAdapter.createMongoAdapter({ client: config.client }),
|
|
19
|
+
readSettings: readSettings(config.client)
|
|
20
|
+
}),
|
|
21
|
+
provider: "mongodb"
|
|
22
|
+
});
|
|
60
23
|
//#endregion
|
|
24
|
+
exports.MongoTransactionUnsupportedError = require_mongodbAdapter.MongoTransactionUnsupportedError;
|
|
61
25
|
exports.mongoAdapter = mongoAdapter;
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MongoTransactionUnsupportedError } from "./mongodbAdapter.cjs";
|
|
2
|
+
import { ToolingDatabase } from "@hot-updater/plugin-core";
|
|
2
3
|
import { MongoClient } from "mongodb";
|
|
3
4
|
//#region src/adapters/mongodb.d.ts
|
|
5
|
+
/** Every write runs in a transaction, which needs a replica set or a sharded cluster. */
|
|
4
6
|
interface MongoDBConfig {
|
|
5
7
|
readonly client: MongoClient;
|
|
6
|
-
/** Enables atomic catalog commits. Insights always requires MongoDB 5+ on a replica set or sharded cluster. */
|
|
7
|
-
readonly transactions?: boolean;
|
|
8
8
|
}
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Hot Updater's database on MongoDB: the storage engine's MongoDB adapter,
|
|
11
|
+
* fenced by the schema settings. `db migrate` creates the collections and
|
|
12
|
+
* indexes, then writes the settings.
|
|
13
|
+
*/
|
|
14
|
+
declare const mongoAdapter: (config: MongoDBConfig) => ToolingDatabase;
|
|
10
15
|
//#endregion
|
|
11
|
-
export { MongoDBConfig, mongoAdapter };
|
|
16
|
+
export { MongoDBConfig, MongoTransactionUnsupportedError, mongoAdapter };
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MongoTransactionUnsupportedError } from "./mongodbAdapter.mjs";
|
|
2
|
+
import { ToolingDatabase } from "@hot-updater/plugin-core";
|
|
2
3
|
import { MongoClient } from "mongodb";
|
|
3
4
|
//#region src/adapters/mongodb.d.ts
|
|
5
|
+
/** Every write runs in a transaction, which needs a replica set or a sharded cluster. */
|
|
4
6
|
interface MongoDBConfig {
|
|
5
7
|
readonly client: MongoClient;
|
|
6
|
-
/** Enables atomic catalog commits. Insights always requires MongoDB 5+ on a replica set or sharded cluster. */
|
|
7
|
-
readonly transactions?: boolean;
|
|
8
8
|
}
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Hot Updater's database on MongoDB: the storage engine's MongoDB adapter,
|
|
11
|
+
* fenced by the schema settings. `db migrate` creates the collections and
|
|
12
|
+
* indexes, then writes the settings.
|
|
13
|
+
*/
|
|
14
|
+
declare const mongoAdapter: (config: MongoDBConfig) => ToolingDatabase;
|
|
10
15
|
//#endregion
|
|
11
|
-
export { MongoDBConfig, mongoAdapter };
|
|
16
|
+
export { MongoDBConfig, MongoTransactionUnsupportedError, mongoAdapter };
|
|
@@ -1,60 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { createMongoReads } from "./mongodbReads.mjs";
|
|
4
|
-
import { createMongoWrites } from "./mongodbWrites.mjs";
|
|
5
|
-
import { compareInsightsText, createDatabasePlugin } from "@hot-updater/plugin-core";
|
|
6
|
-
import { createDatabasePluginAdapter } from "@hot-updater/plugin-core/internal";
|
|
7
|
-
import { MongoServerError } from "mongodb";
|
|
1
|
+
import { MongoTransactionUnsupportedError, createMongoAdapter } from "./mongodbAdapter.mjs";
|
|
2
|
+
import { SETTINGS_TABLE, createEngineDatabase } from "@hot-updater/plugin-core";
|
|
8
3
|
//#region src/adapters/mongodb.ts
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const record = () => client.withSession((recordSession) => recordSession.withTransaction(async () => {
|
|
14
|
-
const records = createMongoCollections(client);
|
|
15
|
-
const options = {
|
|
16
|
-
session: recordSession,
|
|
17
|
-
collation: { locale: "simple" }
|
|
18
|
-
};
|
|
19
|
-
if ((await records.bundleEvents.updateOne({ id: input.event.id }, { $setOnInsert: input.event }, {
|
|
20
|
-
...options,
|
|
21
|
-
upsert: true
|
|
22
|
-
})).upsertedCount === 0) return;
|
|
23
|
-
const current = await records.bundleInstallations.findOne({ install_id: input.installation.install_id }, options);
|
|
24
|
-
if (current === null) await records.bundleInstallations.insertOne({ ...input.installation }, { session: recordSession });
|
|
25
|
-
else if (input.installation.received_at_ms > current.received_at_ms || input.installation.received_at_ms === current.received_at_ms && compareInsightsText(input.installation.id, current.id) > 0) await records.bundleInstallations.updateOne({ install_id: input.installation.install_id }, { $set: input.installation }, options);
|
|
26
|
-
}, {
|
|
27
|
-
readConcern: { level: "snapshot" },
|
|
28
|
-
readPreference: "primary",
|
|
29
|
-
writeConcern: { w: "majority" }
|
|
30
|
-
}));
|
|
31
|
-
try {
|
|
32
|
-
await record();
|
|
33
|
-
} catch (error) {
|
|
34
|
-
if (!(error instanceof MongoServerError) || error.code !== 11e3) throw error;
|
|
35
|
-
await record();
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
...createMongoWrites(collections, session),
|
|
39
|
-
...createMongoReads(collections, session)
|
|
40
|
-
};
|
|
4
|
+
/** Settings rows by their `key` field: the engine's rows and a v0 database's alike. */
|
|
5
|
+
const readSettings = (client) => async () => {
|
|
6
|
+
const rows = await client.db().collection(SETTINGS_TABLE.name).find({ key: { $type: "string" } }).toArray();
|
|
7
|
+
return new Map(rows.map((row) => [String(row.key), row.value]));
|
|
41
8
|
};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const mongoAdapter = (config) => {
|
|
48
|
-
|
|
49
|
-
return Object.assign(createDatabasePlugin({
|
|
9
|
+
/**
|
|
10
|
+
* Hot Updater's database on MongoDB: the storage engine's MongoDB adapter,
|
|
11
|
+
* fenced by the schema settings. `db migrate` creates the collections and
|
|
12
|
+
* indexes, then writes the settings.
|
|
13
|
+
*/
|
|
14
|
+
const mongoAdapter = (config) => ({
|
|
15
|
+
...createEngineDatabase({
|
|
50
16
|
name: "mongodb",
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}),
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
createMigrator: () => createMongoMigrator(config.client)
|
|
57
|
-
});
|
|
58
|
-
};
|
|
17
|
+
adapter: createMongoAdapter({ client: config.client }),
|
|
18
|
+
readSettings: readSettings(config.client)
|
|
19
|
+
}),
|
|
20
|
+
provider: "mongodb"
|
|
21
|
+
});
|
|
59
22
|
//#endregion
|
|
60
|
-
export { mongoAdapter };
|
|
23
|
+
export { MongoTransactionUnsupportedError, mongoAdapter };
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
2
|
+
let mongodb = require("mongodb");
|
|
3
|
+
//#region src/adapters/mongodbAdapter.ts
|
|
4
|
+
var MongoTransactionUnsupportedError = class extends Error {
|
|
5
|
+
name = "MongoTransactionUnsupportedError";
|
|
6
|
+
constructor(cause) {
|
|
7
|
+
super("Hot Updater writes in MongoDB transactions, which need a replica set or a sharded cluster.", { cause });
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
/** A single key column is the `_id`; a composite key is a document in key-column order. */
|
|
11
|
+
const idOf = (table, key) => table.key.length === 1 ? key[0] : Object.fromEntries(table.key.map((column, at) => [column, key[at]]));
|
|
12
|
+
/** A filter on `_id` (never an ObjectId), and on the version when given. */
|
|
13
|
+
const byId = (_id, v) => v === void 0 ? { _id } : {
|
|
14
|
+
_id,
|
|
15
|
+
[_hot_updater_plugin_core.DATABASE_VERSION_COLUMN]: v
|
|
16
|
+
};
|
|
17
|
+
/** MongoDB's TTL monitor deletes a document once its `_expireAt` passes. */
|
|
18
|
+
const TTL = {
|
|
19
|
+
name: "_expireAt",
|
|
20
|
+
key: { _expireAt: 1 },
|
|
21
|
+
expireAfterSeconds: 0
|
|
22
|
+
};
|
|
23
|
+
/** When a row with retention expires; a null retention column never does. */
|
|
24
|
+
const expireAt = ({ retention }, row) => {
|
|
25
|
+
const at = row[retention.column];
|
|
26
|
+
return typeof at === "number" ? new Date(at + retention.ms) : null;
|
|
27
|
+
};
|
|
28
|
+
/** Null columns are left out, so unique indexes skip them as SQL's do. */
|
|
29
|
+
const toDocument = (table, row) => ({
|
|
30
|
+
_id: idOf(table, (0, _hot_updater_plugin_core.rowKey)(table, row)),
|
|
31
|
+
...Object.fromEntries(table.columns.flatMap(({ name }) => row[name] === null || row[name] === void 0 ? [] : [[name, row[name]]])),
|
|
32
|
+
...table.retention && { [TTL.name]: expireAt(table, row) }
|
|
33
|
+
});
|
|
34
|
+
/** `columns op bound` over a tuple prefix, expanded into ORs. */
|
|
35
|
+
const compare = (columns, { values, inclusive }, op) => {
|
|
36
|
+
const terms = values.map((value, position) => ({
|
|
37
|
+
...Object.fromEntries(columns.slice(0, position).map((column, at) => [column, values[at]])),
|
|
38
|
+
[columns[position]]: { [position === values.length - 1 && inclusive ? `${op}e` : op]: value }
|
|
39
|
+
}));
|
|
40
|
+
return terms.length === 1 ? terms[0] : { $or: terms };
|
|
41
|
+
};
|
|
42
|
+
const indexDescription = (table, index) => {
|
|
43
|
+
const columns = index.unique ? index.eq : [...index.eq, ...(0, _hot_updater_plugin_core.indexOrderColumns)(table, index)];
|
|
44
|
+
const exists = columns.filter((column) => (0, _hot_updater_plugin_core.findPhysicalColumn)(table, column).nullable).map((column) => [column, { $exists: true }]);
|
|
45
|
+
return {
|
|
46
|
+
name: index.name,
|
|
47
|
+
key: Object.fromEntries(columns.map((column) => [column, 1])),
|
|
48
|
+
...index.unique && { unique: true },
|
|
49
|
+
...index.unique && exists.length > 0 && { partialFilterExpression: Object.fromEntries(exists) }
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
const mongoError = (error) => error instanceof mongodb.MongoError ? error : void 0;
|
|
53
|
+
/**
|
|
54
|
+
* The storage engine's adapter over MongoDB: one collection per table, the
|
|
55
|
+
* key as `_id`, and indexes as declared, with multi-valued fields as multikey
|
|
56
|
+
* indexes. A write runs in one transaction. Guards are conditional updates,
|
|
57
|
+
* and `check` is a conditional `$inc`: a real write, so a concurrent
|
|
58
|
+
* transaction on the document conflicts.
|
|
59
|
+
*/
|
|
60
|
+
const createMongoAdapter = (options) => {
|
|
61
|
+
const { client, tablePrefix = "", maxOps = 1e3 } = options;
|
|
62
|
+
const collection = (table) => client.db().collection(tablePrefix + table.name);
|
|
63
|
+
const normalize = (table, document) => (0, _hot_updater_plugin_core.normalizeStoredRow)(table, document, { jsonText: false });
|
|
64
|
+
/** Whether the op applied; a guard that no longer matches changes nothing. */
|
|
65
|
+
const apply = async (op, session) => {
|
|
66
|
+
const target = collection(op.table);
|
|
67
|
+
if (op.type === "insert") {
|
|
68
|
+
await target.insertOne(toDocument(op.table, op.row), { session });
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
const _id = idOf(op.table, op.key);
|
|
72
|
+
const update = async (filter, change) => (await target.updateOne(filter, change, { session })).matchedCount === 1;
|
|
73
|
+
switch (op.type) {
|
|
74
|
+
case "patch": {
|
|
75
|
+
const $set = { [_hot_updater_plugin_core.DATABASE_VERSION_COLUMN]: op.guard.v + 1 };
|
|
76
|
+
const $unset = {};
|
|
77
|
+
for (const [name, value] of Object.entries(op.set)) if (value === null) $unset[name] = "";
|
|
78
|
+
else $set[name] = value;
|
|
79
|
+
if (op.table.retention) $set[TTL.name] = expireAt(op.table, {
|
|
80
|
+
...op.previous,
|
|
81
|
+
...op.set
|
|
82
|
+
});
|
|
83
|
+
return update(byId(_id, op.guard.v), {
|
|
84
|
+
$set,
|
|
85
|
+
$unset
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
case "delete": return (await target.deleteOne(byId(_id, op.guard.v), { session })).deletedCount === 1;
|
|
89
|
+
case "check": return update(byId(_id, op.guard.v), { $inc: { _checked: 1 } });
|
|
90
|
+
case "increment": {
|
|
91
|
+
if (op.init === void 0 || op.guard !== void 0) return update(byId(_id, op.guard?.v), { $inc: {
|
|
92
|
+
...op.by,
|
|
93
|
+
[_hot_updater_plugin_core.DATABASE_VERSION_COLUMN]: 1
|
|
94
|
+
} });
|
|
95
|
+
const set = {};
|
|
96
|
+
for (const { name } of op.table.columns) {
|
|
97
|
+
const start = op.init[name] ?? null;
|
|
98
|
+
const by = name === _hot_updater_plugin_core.DATABASE_VERSION_COLUMN ? 1 : op.by[name];
|
|
99
|
+
const stored = { $ifNull: [`$${name}`, { $literal: start ?? 0 }] };
|
|
100
|
+
if (by !== void 0) set[name] = { $add: [stored, by] };
|
|
101
|
+
else if (start !== null) set[name] = stored;
|
|
102
|
+
}
|
|
103
|
+
if (op.table.retention) set[TTL.name] = expireAt(op.table, op.init);
|
|
104
|
+
await target.updateOne(byId(_id), [{ $set: set }], {
|
|
105
|
+
upsert: true,
|
|
106
|
+
session
|
|
107
|
+
});
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
return {
|
|
113
|
+
id: "mongodb",
|
|
114
|
+
fits: (ops) => ops.length <= maxOps,
|
|
115
|
+
async get(table, keys) {
|
|
116
|
+
if (keys.length === 0) return [];
|
|
117
|
+
const ids = keys.map((key) => idOf(table, key));
|
|
118
|
+
const documents = await collection(table).find(byId({ $in: ids })).toArray();
|
|
119
|
+
const found = new Map(documents.map((document) => [JSON.stringify(document._id), document]));
|
|
120
|
+
return ids.map((id) => {
|
|
121
|
+
const document = found.get(JSON.stringify(id));
|
|
122
|
+
return document === void 0 ? null : normalize(table, document);
|
|
123
|
+
});
|
|
124
|
+
},
|
|
125
|
+
async query(table, request) {
|
|
126
|
+
const index = (0, _hot_updater_plugin_core.findPhysicalIndex)(table, request.index);
|
|
127
|
+
const columns = (0, _hot_updater_plugin_core.indexOrderColumns)(table, index);
|
|
128
|
+
const bounds = [...request.lower ? [compare(columns, request.lower, "$gt")] : [], ...request.upper ? [compare(columns, request.upper, "$lt")] : []];
|
|
129
|
+
const direction = request.order === "asc" ? 1 : -1;
|
|
130
|
+
return (await collection(table).find({
|
|
131
|
+
...Object.fromEntries(index.eq.map((column, at) => [column, request.eq[at]])),
|
|
132
|
+
...bounds.length > 0 && { $and: bounds }
|
|
133
|
+
}, {
|
|
134
|
+
sort: Object.fromEntries(columns.map((column) => [column, direction])),
|
|
135
|
+
limit: request.limit,
|
|
136
|
+
...options.batchSize && { batchSize: options.batchSize }
|
|
137
|
+
}).toArray()).map((document) => normalize(table, document));
|
|
138
|
+
},
|
|
139
|
+
async write(ops) {
|
|
140
|
+
const session = client.startSession();
|
|
141
|
+
let position = 0;
|
|
142
|
+
try {
|
|
143
|
+
session.startTransaction({
|
|
144
|
+
readConcern: { level: "snapshot" },
|
|
145
|
+
writeConcern: { w: "majority" }
|
|
146
|
+
});
|
|
147
|
+
for (; position < ops.length; position += 1) if (!await apply(ops[position], session)) {
|
|
148
|
+
await session.abortTransaction();
|
|
149
|
+
return {
|
|
150
|
+
ok: false,
|
|
151
|
+
failedOp: position
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
await session.commitTransaction().catch(async (error) => {
|
|
155
|
+
if (!mongoError(error)?.hasErrorLabel("UnknownTransactionCommitResult")) throw error;
|
|
156
|
+
await session.commitTransaction();
|
|
157
|
+
});
|
|
158
|
+
return { ok: true };
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if (session.inTransaction()) await session.abortTransaction().catch(() => void 0);
|
|
161
|
+
const failure = mongoError(error);
|
|
162
|
+
if (failure?.hasErrorLabel("TransientTransactionError") || failure?.code === 112) return {
|
|
163
|
+
ok: false,
|
|
164
|
+
retry: true
|
|
165
|
+
};
|
|
166
|
+
if (failure?.code === 11e3 && position < ops.length) return ops[position].type === "increment" ? {
|
|
167
|
+
ok: false,
|
|
168
|
+
retry: true
|
|
169
|
+
} : {
|
|
170
|
+
ok: false,
|
|
171
|
+
failedOp: position
|
|
172
|
+
};
|
|
173
|
+
throw failure?.code === 20 ? new MongoTransactionUnsupportedError(error) : error;
|
|
174
|
+
} finally {
|
|
175
|
+
await session.endSession();
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
migrations: { async apply(tables) {
|
|
179
|
+
for (const table of tables) {
|
|
180
|
+
await client.db().createCollection(tablePrefix + table.name).catch((error) => {
|
|
181
|
+
if (mongoError(error)?.code !== 48) throw error;
|
|
182
|
+
});
|
|
183
|
+
if (table.retention) await collection(table).createIndexes([TTL]);
|
|
184
|
+
if (table.indexes.length === 0) continue;
|
|
185
|
+
await collection(table).createIndexes(table.indexes.map((index) => indexDescription(table, index)));
|
|
186
|
+
}
|
|
187
|
+
} }
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
//#endregion
|
|
191
|
+
exports.MongoTransactionUnsupportedError = MongoTransactionUnsupportedError;
|
|
192
|
+
exports.createMongoAdapter = createMongoAdapter;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "@hot-updater/plugin-core";
|
|
2
|
+
import { MongoClient } from "mongodb";
|
|
3
|
+
//#region src/adapters/mongodbAdapter.d.ts
|
|
4
|
+
declare class MongoTransactionUnsupportedError extends Error {
|
|
5
|
+
readonly name = "MongoTransactionUnsupportedError";
|
|
6
|
+
constructor(cause: unknown);
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { MongoTransactionUnsupportedError };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "@hot-updater/plugin-core";
|
|
2
|
+
import { MongoClient } from "mongodb";
|
|
3
|
+
//#region src/adapters/mongodbAdapter.d.ts
|
|
4
|
+
declare class MongoTransactionUnsupportedError extends Error {
|
|
5
|
+
readonly name = "MongoTransactionUnsupportedError";
|
|
6
|
+
constructor(cause: unknown);
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { MongoTransactionUnsupportedError };
|