@hot-updater/server 1.0.0-rc.1 → 1.0.0-rc.16
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/drizzle.cjs +35 -69
- package/dist/adapters/drizzle.d.cts +13 -6
- package/dist/adapters/drizzle.d.mts +13 -6
- package/dist/adapters/drizzle.mjs +34 -69
- 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 +25 -31
- package/dist/adapters/kysely.d.cts +10 -7
- package/dist/adapters/kysely.d.mts +10 -7
- package/dist/adapters/kysely.mjs +25 -31
- package/dist/adapters/kyselyExecutor.cjs +32 -0
- package/dist/adapters/kyselyExecutor.d.cts +12 -0
- package/dist/adapters/kyselyExecutor.d.mts +12 -0
- package/dist/adapters/kyselyExecutor.mjs +32 -0
- package/dist/adapters/mongodb.cjs +28 -27
- package/dist/adapters/mongodb.d.cts +10 -5
- package/dist/adapters/mongodb.d.mts +10 -5
- package/dist/adapters/mongodb.mjs +28 -27
- package/dist/adapters/mongodbAdapter.cjs +174 -0
- package/dist/adapters/mongodbAdapter.d.cts +9 -0
- package/dist/adapters/mongodbAdapter.d.mts +9 -0
- package/dist/adapters/mongodbAdapter.mjs +173 -0
- package/dist/adapters/prisma.cjs +38 -220
- package/dist/adapters/prisma.d.cts +12 -8
- package/dist/adapters/prisma.d.mts +12 -8
- package/dist/adapters/prisma.mjs +38 -219
- package/dist/adapters/prismaExecutor.cjs +64 -0
- package/dist/adapters/prismaExecutor.mjs +64 -0
- package/dist/adapters/sqlProviders.cjs +9 -0
- package/dist/adapters/sqlProviders.mjs +9 -0
- package/dist/apiKeys.cjs +8 -8
- package/dist/apiKeys.d.cts +1 -24
- package/dist/apiKeys.d.mts +1 -24
- package/dist/apiKeys.mjs +5 -9
- package/dist/assembly/assemblePlugins.cjs +147 -0
- package/dist/assembly/assemblePlugins.d.cts +12 -0
- package/dist/assembly/assemblePlugins.d.mts +12 -0
- package/dist/assembly/assemblePlugins.mjs +146 -0
- package/dist/assembly/databasePlugins.cjs +23 -0
- package/dist/assembly/databasePlugins.d.cts +43 -0
- package/dist/assembly/databasePlugins.d.mts +43 -0
- package/dist/assembly/databasePlugins.mjs +22 -0
- package/dist/core/api.cjs +91 -0
- package/dist/core/api.d.cts +65 -0
- package/dist/core/api.d.mts +65 -0
- package/dist/core/api.mjs +87 -0
- package/dist/core/baseCandidates.cjs +71 -0
- package/dist/core/baseCandidates.d.cts +17 -0
- package/dist/core/baseCandidates.d.mts +17 -0
- package/dist/core/baseCandidates.mjs +69 -0
- package/dist/core/operations.cjs +350 -0
- package/dist/core/operations.mjs +350 -0
- package/dist/core/reads.cjs +273 -0
- package/dist/core/reads.d.cts +48 -0
- package/dist/core/reads.d.mts +48 -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/schema.cjs +279 -0
- package/dist/core/schema.d.cts +307 -0
- package/dist/core/schema.d.mts +307 -0
- package/dist/core/schema.mjs +277 -0
- package/dist/core/writes.cjs +96 -0
- package/dist/core/writes.mjs +91 -0
- package/dist/createHotUpdaterCore.cjs +61 -63
- package/dist/createHotUpdaterCore.d.cts +53 -45
- package/dist/createHotUpdaterCore.d.mts +53 -45
- package/dist/createHotUpdaterCore.mjs +61 -63
- package/dist/database/cursor.cjs +44 -0
- package/dist/database/cursor.d.cts +7 -0
- package/dist/database/cursor.d.mts +7 -0
- package/dist/database/cursor.mjs +40 -0
- package/dist/database/database.cjs +44 -0
- package/dist/database/database.d.cts +123 -0
- package/dist/database/database.d.mts +123 -0
- package/dist/database/database.mjs +44 -0
- package/dist/database/definitions.d.cts +68 -0
- package/dist/database/definitions.d.mts +68 -0
- package/dist/database/engine.cjs +37 -0
- package/dist/database/engine.d.cts +40 -0
- package/dist/database/engine.d.mts +40 -0
- package/dist/database/engine.mjs +37 -0
- package/dist/database/engineAggregates.cjs +115 -0
- package/dist/database/engineAggregates.mjs +112 -0
- package/dist/database/engineReads.cjs +180 -0
- package/dist/database/engineReads.d.cts +35 -0
- package/dist/database/engineReads.d.mts +35 -0
- package/dist/database/engineReads.mjs +179 -0
- package/dist/database/engineTransaction.cjs +403 -0
- package/dist/database/engineTransaction.d.cts +26 -0
- package/dist/database/engineTransaction.d.mts +26 -0
- package/dist/database/engineTransaction.mjs +402 -0
- package/dist/database/errors.cjs +27 -0
- package/dist/database/errors.d.cts +21 -0
- package/dist/database/errors.d.mts +21 -0
- package/dist/database/errors.mjs +24 -0
- package/dist/database/fence.cjs +124 -0
- package/dist/database/fence.d.cts +42 -0
- package/dist/database/fence.d.mts +42 -0
- package/dist/database/fence.mjs +116 -0
- package/dist/database/index.cjs +127 -0
- package/dist/database/index.d.cts +17 -0
- package/dist/database/index.d.mts +17 -0
- package/dist/database/index.mjs +15 -0
- package/dist/database/kv/kvAdapter.cjs +273 -0
- package/dist/database/kv/kvAdapter.d.cts +101 -0
- package/dist/database/kv/kvAdapter.d.mts +101 -0
- package/dist/database/kv/kvAdapter.mjs +272 -0
- package/dist/database/resolveSchema.cjs +196 -0
- package/dist/database/resolveSchema.d.cts +42 -0
- package/dist/database/resolveSchema.d.mts +42 -0
- package/dist/database/resolveSchema.mjs +193 -0
- package/dist/database/schema.cjs +21 -0
- package/dist/database/schema.d.cts +61 -0
- package/dist/database/schema.d.mts +61 -0
- package/dist/database/schema.mjs +20 -0
- package/dist/database/sql/sqlAdapter.cjs +282 -0
- package/dist/database/sql/sqlAdapter.d.cts +46 -0
- package/dist/database/sql/sqlAdapter.d.mts +46 -0
- package/dist/database/sql/sqlAdapter.mjs +279 -0
- package/dist/database/sql/sqlSchema.cjs +115 -0
- package/dist/database/sql/sqlSchema.d.cts +8 -0
- package/dist/database/sql/sqlSchema.d.mts +8 -0
- package/dist/database/sql/sqlSchema.mjs +111 -0
- package/dist/db/builtInDatabase.cjs +104 -0
- package/dist/db/builtInDatabase.d.cts +38 -0
- package/dist/db/builtInDatabase.d.mts +38 -0
- package/dist/db/builtInDatabase.mjs +97 -0
- package/dist/db/createBundleDiff.cjs +6 -6
- package/dist/db/createBundleDiff.d.cts +4 -7
- package/dist/db/createBundleDiff.d.mts +4 -7
- package/dist/db/createBundleDiff.mjs +5 -5
- package/dist/db/engineDrizzleSchema.cjs +54 -0
- package/dist/db/engineDrizzleSchema.mjs +54 -0
- package/dist/db/engineMigrator.cjs +53 -0
- package/dist/db/engineMigrator.mjs +53 -0
- package/dist/db/enginePrismaSchema.cjs +85 -0
- package/dist/db/enginePrismaSchema.d.cts +5 -0
- package/dist/db/enginePrismaSchema.d.mts +5 -0
- package/dist/db/enginePrismaSchema.mjs +84 -0
- package/dist/db/engineSql.cjs +26 -0
- package/dist/db/engineSql.d.cts +17 -0
- package/dist/db/engineSql.d.mts +17 -0
- package/dist/db/engineSql.mjs +25 -0
- package/dist/db/engineSqlMigrator.cjs +66 -0
- package/dist/db/engineSqlMigrator.mjs +66 -0
- package/dist/db/fixedMigratorShared.cjs +0 -11
- package/dist/db/fixedMigratorShared.mjs +1 -8
- package/dist/db/index.cjs +23 -8
- package/dist/db/index.d.cts +10 -4
- package/dist/db/index.d.mts +10 -4
- package/dist/db/index.mjs +16 -8
- package/dist/db/releaseCatalog.cjs +20 -44
- package/dist/db/releaseCatalog.d.cts +2 -3
- package/dist/db/releaseCatalog.d.mts +2 -3
- package/dist/db/releaseCatalog.mjs +20 -44
- package/dist/db/schemaSettings.cjs +63 -0
- package/dist/db/schemaSettings.d.cts +12 -0
- package/dist/db/schemaSettings.d.mts +12 -0
- package/dist/db/schemaSettings.mjs +62 -0
- package/dist/db/settingsMigrator.cjs +92 -0
- package/dist/db/settingsMigrator.mjs +89 -0
- package/dist/db/types.cjs +3 -12
- package/dist/db/types.d.cts +26 -69
- package/dist/db/types.d.mts +26 -69
- package/dist/db/types.mjs +2 -11
- package/dist/db/updateArtifacts.cjs +38 -68
- package/dist/db/updateArtifacts.mjs +40 -69
- package/dist/handler.cjs +72 -43
- package/dist/handler.d.cts +3 -6
- package/dist/handler.d.mts +3 -6
- package/dist/handler.mjs +73 -43
- package/dist/handlerAdminRoutes.cjs +375 -0
- package/dist/handlerAdminRoutes.mjs +373 -0
- package/dist/handlerParameters.cjs +6 -11
- package/dist/handlerParameters.mjs +6 -10
- package/dist/handlerReleaseCatalogRoutes.cjs +11 -14
- package/dist/handlerReleaseCatalogRoutes.mjs +11 -13
- package/dist/handlerTypes.d.cts +2 -56
- package/dist/handlerTypes.d.mts +2 -56
- package/dist/handlerVersionRoutes.cjs +20 -4
- package/dist/handlerVersionRoutes.d.cts +1 -0
- package/dist/handlerVersionRoutes.d.mts +1 -0
- package/dist/handlerVersionRoutes.mjs +20 -4
- package/dist/index.cjs +4 -7
- package/dist/index.d.cts +10 -9
- package/dist/index.d.mts +10 -9
- package/dist/index.mjs +4 -4
- package/dist/insights/domain.d.cts +53 -70
- package/dist/insights/domain.d.mts +53 -70
- package/dist/insights/errors.cjs +35 -8
- package/dist/insights/errors.mjs +35 -8
- package/dist/insights/eventInput.cjs +64 -24
- package/dist/insights/eventInput.mjs +63 -25
- package/dist/insights/provider.cjs +356 -0
- package/dist/insights/provider.d.cts +6 -0
- package/dist/insights/provider.d.mts +6 -0
- package/dist/insights/provider.mjs +355 -0
- package/dist/insights/queryInput.cjs +78 -43
- package/dist/insights/queryInput.mjs +76 -40
- package/dist/insights/routes.cjs +94 -34
- package/dist/insights/routes.mjs +93 -35
- package/dist/insights/types.d.cts +27 -12
- package/dist/insights/types.d.mts +27 -12
- package/dist/node.d.cts +1 -2
- package/dist/node.d.mts +1 -2
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/plugins/api-keys/index.cjs +50 -0
- package/dist/plugins/api-keys/index.d.cts +85 -0
- package/dist/plugins/api-keys/index.d.mts +85 -0
- package/dist/plugins/api-keys/index.mjs +47 -0
- package/dist/plugins/api-keys/model.cjs +58 -0
- package/dist/plugins/api-keys/model.d.cts +8 -0
- package/dist/plugins/api-keys/model.d.mts +8 -0
- package/dist/plugins/api-keys/model.mjs +58 -0
- package/dist/plugins/api-keys/schema.cjs +38 -0
- package/dist/plugins/api-keys/schema.d.cts +44 -0
- package/dist/plugins/api-keys/schema.d.mts +44 -0
- package/dist/plugins/api-keys/schema.mjs +39 -0
- package/dist/plugins/builtIn.cjs +7 -0
- package/dist/plugins/builtIn.mjs +6 -0
- package/dist/plugins/definePlugin.cjs +5 -0
- package/dist/plugins/definePlugin.d.cts +73 -0
- package/dist/plugins/definePlugin.d.mts +73 -0
- package/dist/plugins/definePlugin.mjs +5 -0
- package/dist/plugins/index.cjs +17 -0
- package/dist/plugins/index.d.cts +9 -0
- package/dist/plugins/index.d.mts +9 -0
- package/dist/plugins/index.mjs +7 -0
- package/dist/plugins/insights/index.cjs +48 -0
- package/dist/plugins/insights/index.d.cts +295 -0
- package/dist/plugins/insights/index.d.mts +295 -0
- package/dist/plugins/insights/index.mjs +44 -0
- package/dist/plugins/insights/model.cjs +17 -0
- package/dist/plugins/insights/model.d.cts +10 -0
- package/dist/plugins/insights/model.d.mts +10 -0
- package/dist/plugins/insights/model.mjs +17 -0
- package/dist/plugins/insights/reads.cjs +471 -0
- package/dist/plugins/insights/reads.mjs +466 -0
- package/dist/plugins/insights/recordEvent.cjs +135 -0
- package/dist/plugins/insights/recordEvent.d.cts +13 -0
- package/dist/plugins/insights/recordEvent.d.mts +13 -0
- package/dist/plugins/insights/recordEvent.mjs +132 -0
- package/dist/plugins/insights/schema.cjs +347 -0
- package/dist/plugins/insights/schema.d.cts +258 -0
- package/dist/plugins/insights/schema.d.mts +258 -0
- package/dist/plugins/insights/schema.mjs +344 -0
- package/dist/storageAccess.cjs +0 -1
- package/dist/types/index.d.cts +2 -29
- package/dist/types/index.d.mts +2 -29
- package/package.json +30 -7
- package/src/adapters/drizzle.conformance.integration.spec.ts +34 -0
- package/src/adapters/drizzle.readBudgets.integration.spec.ts +41 -0
- package/src/adapters/drizzle.spec.ts +277 -208
- package/src/adapters/drizzle.ts +48 -128
- package/src/adapters/drizzleExecutor.ts +166 -0
- package/src/adapters/kysely.conformance.integration.spec.ts +36 -0
- package/src/adapters/kysely.readBudgets.integration.spec.ts +42 -0
- package/src/adapters/kysely.spec.ts +212 -117
- package/src/adapters/kysely.ts +32 -87
- package/src/adapters/kyselyExecutor.ts +53 -0
- package/src/adapters/mongodb.integration.spec.ts +180 -0
- package/src/adapters/mongodb.readBudgets.integration.spec.ts +61 -0
- package/src/adapters/mongodb.ts +36 -65
- package/src/adapters/mongodbAdapter.ts +293 -0
- package/src/adapters/prisma.conformance.integration.spec.ts +36 -0
- package/src/adapters/prisma.integration.spec.ts +138 -0
- package/src/adapters/prisma.readBudgets.integration.spec.ts +40 -0
- package/src/adapters/prisma.spec.ts +226 -173
- package/src/adapters/prisma.ts +60 -451
- package/src/adapters/prismaExecutor.ts +107 -0
- package/src/adapters/prismaTestClients.ts +175 -0
- package/src/adapters/sqlProviders.ts +14 -0
- package/src/apiKeys.integration.spec.ts +19 -119
- package/src/apiKeys.spec.ts +39 -35
- package/src/apiKeys.ts +2 -8
- package/src/assembly/assemblePlugins.ts +269 -0
- package/src/assembly/assembly.spec.ts +325 -0
- package/src/assembly/assembly.types.spec.ts +155 -0
- package/src/assembly/builtInRoutes.spec.ts +213 -0
- package/src/assembly/databasePlugins.spec.ts +71 -0
- package/src/assembly/databasePlugins.ts +96 -0
- package/src/core/api.ts +139 -0
- package/src/core/baseCandidates.spec.ts +378 -0
- package/src/core/baseCandidates.ts +136 -0
- package/src/core/index.ts +44 -0
- package/src/core/operations.spec.ts +415 -0
- package/src/core/operations.ts +551 -0
- package/src/core/reads.spec.ts +300 -0
- package/src/core/reads.ts +417 -0
- package/src/core/releases.spec.ts +308 -0
- package/src/core/releases.ts +345 -0
- package/src/core/schema.ts +173 -0
- package/src/core/writes.ts +160 -0
- package/src/createHotUpdaterCore.ts +191 -167
- package/src/database/cursor.ts +65 -0
- package/src/database/database.ts +335 -0
- package/src/database/database.types.spec.ts +135 -0
- package/src/database/definitions.ts +72 -0
- package/src/database/engine.ts +62 -0
- package/src/database/engineAggregates.spec.ts +539 -0
- package/src/database/engineAggregates.ts +193 -0
- package/src/database/engineReads.spec.ts +219 -0
- package/src/database/engineReads.ts +302 -0
- package/src/database/engineTransaction.spec.ts +710 -0
- package/src/database/engineTransaction.ts +588 -0
- package/src/database/errors.ts +30 -0
- package/src/database/fence.spec.ts +223 -0
- package/src/database/fence.ts +171 -0
- package/src/database/index.ts +154 -0
- package/src/database/kv/kvAdapter.conformance.integration.spec.ts +17 -0
- package/src/database/kv/kvAdapter.readBudgets.integration.spec.ts +17 -0
- package/src/database/kv/kvAdapter.spec.ts +468 -0
- package/src/database/kv/kvAdapter.ts +450 -0
- package/src/database/kv/kvTestStore.ts +91 -0
- package/src/database/memory.readBudgets.integration.spec.ts +13 -0
- package/src/database/resolveSchema.spec.ts +230 -0
- package/src/database/resolveSchema.ts +372 -0
- package/src/database/schema.ts +169 -0
- package/src/database/schema.types.spec.ts +94 -0
- package/src/database/sql/docker-compose.yml +36 -0
- package/src/database/sql/sqlAdapter.integration.spec.ts +148 -0
- package/src/database/sql/sqlAdapter.readBudgets.integration.spec.ts +109 -0
- package/src/database/sql/sqlAdapter.spec.ts +255 -0
- package/src/database/sql/sqlAdapter.ts +532 -0
- package/src/database/sql/sqlSchema.ts +205 -0
- package/src/database/sql/sqlTestExecutors.ts +183 -0
- package/src/databaseTestSuite.spec.ts +39 -0
- package/src/db/builtInDatabase.ts +149 -0
- package/src/db/bundleRows.spec.ts +3 -3
- package/src/db/createBundleDiff.spec.ts +43 -29
- package/src/db/createBundleDiff.ts +13 -7
- package/src/db/engineDrizzleSchema.ts +72 -0
- package/src/db/engineMigrator.ts +105 -0
- package/src/db/enginePrismaSchema.ts +147 -0
- package/src/db/engineSql.spec.ts +129 -0
- package/src/db/engineSql.ts +48 -0
- package/src/db/engineSqlMigrator.ts +116 -0
- package/src/db/fixedMigratorShared.ts +1 -20
- package/src/db/index.spec.ts +116 -824
- package/src/db/index.ts +43 -14
- package/src/db/pluginTables.spec.ts +218 -0
- package/src/db/releaseCatalog.ts +48 -90
- package/src/db/schemaSettings.ts +104 -0
- package/src/db/settingsMigrator.spec.ts +65 -0
- package/src/db/settingsMigrator.ts +152 -0
- package/src/db/types.ts +25 -165
- package/src/db/updateArtifacts.spec.ts +170 -294
- package/src/db/updateArtifacts.ts +74 -142
- package/src/db/updateCheck.bench.ts +47 -0
- package/src/handler-standalone.integration.spec.ts +204 -412
- package/src/handler.spec.ts +134 -51
- package/src/handler.testFixtures.ts +14 -19
- package/src/handler.ts +163 -75
- package/src/handlerAdminRoutes.spec.ts +183 -0
- package/src/handlerAdminRoutes.ts +536 -0
- package/src/handlerAuth.integration.spec.ts +3 -3
- package/src/handlerManagement.spec.ts +136 -196
- package/src/handlerReleaseCatalogRoutes.ts +15 -17
- package/src/handlerTypes.ts +3 -80
- package/src/handlerVersionRoutes.ts +20 -7
- package/src/index.ts +7 -14
- package/src/insights/domain.ts +56 -77
- package/src/insights/errors.spec.ts +48 -0
- package/src/insights/errors.ts +50 -6
- package/src/insights/eventInput.ts +80 -27
- package/src/insights/insights.integration.spec.ts +525 -44
- package/src/insights/provider.spec.ts +574 -0
- package/src/insights/provider.ts +667 -0
- package/src/insights/queryInput.ts +113 -73
- package/src/insights/routes.ts +125 -69
- package/src/insights/types.ts +47 -36
- package/src/lintRules.spec.ts +76 -0
- package/src/plugins/api-keys/apiKeysPlugin.spec.ts +172 -0
- package/src/plugins/api-keys/index.ts +66 -0
- package/src/plugins/api-keys/model.ts +69 -0
- package/src/plugins/api-keys/schema.ts +22 -0
- package/src/plugins/builtIn.ts +5 -0
- package/src/plugins/definePlugin.ts +100 -0
- package/src/plugins/index.ts +55 -0
- package/src/plugins/insights/index.ts +86 -0
- package/src/plugins/insights/insightsRollout.integration.spec.ts +187 -0
- package/src/plugins/insights/model.spec.ts +66 -0
- package/src/plugins/insights/model.ts +19 -0
- package/src/plugins/insights/reads.spec.ts +725 -0
- package/src/plugins/insights/reads.ts +707 -0
- package/src/plugins/insights/recordEvent.spec.ts +443 -0
- package/src/plugins/insights/recordEvent.ts +238 -0
- package/src/plugins/insights/schema.ts +229 -0
- package/src/plugins/pluginTestHarness.spec.ts +56 -0
- package/src/readBudgets.testFixtures.ts +15 -0
- package/src/releaseCatalogRoutes.integration.spec.ts +47 -92
- package/src/runtime.spec.ts +91 -77
- package/src/runtime.testFixtures.ts +28 -44
- package/src/runtimeBundles.integration.spec.ts +112 -0
- package/src/testUtilsMutation.integration.spec.ts +215 -0
- package/src/testUtilsPackage.integration.spec.ts +176 -0
- package/src/types/index.ts +0 -32
- package/dist/adapters/databaseConstraintErrors.cjs +0 -23
- package/dist/adapters/databaseConstraintErrors.mjs +0 -21
- package/dist/adapters/databasePluginUtils.cjs +0 -117
- package/dist/adapters/databasePluginUtils.mjs +0 -106
- package/dist/adapters/drizzleCrud.cjs +0 -250
- package/dist/adapters/drizzleCrud.mjs +0 -249
- package/dist/adapters/drizzleLazyDB.cjs +0 -101
- package/dist/adapters/drizzleLazyDB.mjs +0 -101
- package/dist/adapters/drizzleQuery.cjs +0 -68
- package/dist/adapters/drizzleQuery.mjs +0 -67
- package/dist/adapters/kyselyCrud.cjs +0 -254
- package/dist/adapters/kyselyCrud.mjs +0 -253
- package/dist/adapters/kyselyQuery.cjs +0 -56
- package/dist/adapters/kyselyQuery.mjs +0 -55
- package/dist/adapters/mongodbCollections.cjs +0 -36
- package/dist/adapters/mongodbCollections.mjs +0 -30
- package/dist/adapters/mongodbQuery.cjs +0 -77
- package/dist/adapters/mongodbQuery.mjs +0 -70
- package/dist/adapters/mongodbReads.cjs +0 -148
- package/dist/adapters/mongodbReads.mjs +0 -147
- package/dist/adapters/mongodbWrites.cjs +0 -134
- package/dist/adapters/mongodbWrites.mjs +0 -133
- package/dist/adapters/prismaQuery.cjs +0 -58
- package/dist/adapters/prismaQuery.mjs +0 -56
- package/dist/adapters/prismaRows.cjs +0 -198
- package/dist/adapters/prismaRows.mjs +0 -188
- package/dist/db/databasePluginCore.cjs +0 -138
- 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 -319
- package/dist/db/fixedMigratorMongo.mjs +0 -319
- package/dist/db/mongoMigrationExecution.cjs +0 -11
- package/dist/db/mongoMigrationExecution.mjs +0 -11
- 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 -101
- 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 -256
- package/dist/db/schemaGenerators.mjs +0 -254
- package/dist/db/schemaReadiness.cjs +0 -24
- package/dist/db/schemaReadiness.d.cts +0 -8
- package/dist/db/schemaReadiness.d.mts +0 -8
- package/dist/db/schemaReadiness.mjs +0 -23
- package/dist/db/sqlMigrationExecution.cjs +0 -67
- package/dist/db/sqlMigrationExecution.mjs +0 -66
- package/dist/handlerBundleRoutes.cjs +0 -155
- package/dist/handlerBundleRoutes.mjs +0 -155
- package/dist/handlerReleaseManagementRoutes.cjs +0 -125
- package/dist/handlerReleaseManagementRoutes.mjs +0 -124
- 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/dist/schema/dsl.cjs +0 -103
- package/dist/schema/dsl.mjs +0 -87
- package/dist/schema/index.cjs +0 -6
- 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 -364
- package/dist/schema/v1_0_0.mjs +0 -357
- package/src/adapters/databaseConstraintErrors.ts +0 -25
- package/src/adapters/databasePluginTestDatabase.ts +0 -106
- package/src/adapters/databasePluginUtils.spec.ts +0 -29
- package/src/adapters/databasePluginUtils.ts +0 -214
- package/src/adapters/drizzleCrud.ts +0 -419
- package/src/adapters/drizzleLazyDB.ts +0 -257
- package/src/adapters/drizzleQuery.ts +0 -164
- package/src/adapters/kyselyCrud.ts +0 -588
- package/src/adapters/kyselyQuery.ts +0 -128
- package/src/adapters/mongodb.spec.ts +0 -141
- package/src/adapters/mongodbCollections.ts +0 -62
- package/src/adapters/mongodbQuery.ts +0 -226
- package/src/adapters/mongodbReads.ts +0 -311
- package/src/adapters/mongodbRows.spec.ts +0 -64
- package/src/adapters/mongodbRows.ts +0 -118
- package/src/adapters/mongodbTestClient.ts +0 -342
- package/src/adapters/mongodbTestFilter.ts +0 -166
- package/src/adapters/mongodbWrites.ts +0 -260
- package/src/adapters/prismaQuery.ts +0 -129
- package/src/adapters/prismaRows.spec.ts +0 -98
- package/src/adapters/prismaRows.ts +0 -301
- package/src/adapters/prismaTestClient.ts +0 -396
- package/src/calculatePagination.ts +0 -34
- 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 -107
- package/src/db/fixedMigrator.spec.ts +0 -231
- package/src/db/fixedMigrator.ts +0 -147
- package/src/db/fixedMigratorMongo.spec.ts +0 -192
- package/src/db/fixedMigratorMongo.ts +0 -425
- package/src/db/hotUpdaterSchema.ts +0 -5
- package/src/db/mongoMigrationExecution.ts +0 -23
- package/src/db/schema/definitions.ts +0 -1
- package/src/db/schema/mongodb.ts +0 -40
- package/src/db/schema/registry.ts +0 -55
- package/src/db/schema/sql.ts +0 -241
- package/src/db/schema/sqlOperations.ts +0 -63
- package/src/db/schema/types.ts +0 -1
- package/src/db/schemaGenerators.ts +0 -466
- 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 -55
- package/src/handlerBundleRoutes.ts +0 -259
- package/src/handlerReleaseManagementRoutes.ts +0 -213
- 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
- package/src/schema/dsl-all-versions.spec.ts +0 -35
- 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 -146
- package/src/schema/v1_0_0.ts +0 -465
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { ReleaseCatalogRequest } from "../db/releaseCatalog.mjs";
|
|
2
|
+
import { CoreDatabase, CoreStorage } from "./reads.mjs";
|
|
3
|
+
import { HotUpdaterCoreApi } from "@hot-updater/plugin-core";
|
|
4
|
+
import { DatabaseAdapter } from "@hot-updater/plugin-core/internal";
|
|
5
|
+
//#region src/core/api.d.ts
|
|
6
|
+
interface CoreApiOptions {
|
|
7
|
+
readonly now?: () => number;
|
|
8
|
+
/** The database's CDN purge, called after a write that changes a Release Catalog. */
|
|
9
|
+
readonly onCachedRoutesChange?: () => Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
/** Core's reads and typed writes over one database handle. */
|
|
12
|
+
declare const createCoreApi: (db: CoreDatabase, storage: CoreStorage, options?: CoreApiOptions) => {
|
|
13
|
+
/** One read, which checks the schema settings first. */
|
|
14
|
+
ready: () => Promise<void>;
|
|
15
|
+
deploy: (deployments: readonly import("@hot-updater/plugin-core").Deployment[]) => Promise<import("@hot-updater/plugin-core").ReleaseCatalogMutationResult[]>;
|
|
16
|
+
updateReleasePolicy: (input: import("@hot-updater/plugin-core").ReleaseTarget & {
|
|
17
|
+
readonly patch: import("@hot-updater/plugin-core").ReleasePolicyPatch;
|
|
18
|
+
}) => Promise<import("@hot-updater/plugin-core").ReleaseCatalogMutationResult>;
|
|
19
|
+
preflightReleasePolicy: (input: import("@hot-updater/plugin-core").ReleaseTarget & {
|
|
20
|
+
readonly patch: import("@hot-updater/plugin-core").ReleasePolicyPatch;
|
|
21
|
+
}) => Promise<import("@hot-updater/plugin-core").ReleaseCatalogMutationPreflight>;
|
|
22
|
+
deleteRelease: (input: import("@hot-updater/plugin-core").ReleaseTarget) => Promise<import("@hot-updater/plugin-core").ReleaseCatalogMutationResult>;
|
|
23
|
+
promoteRelease: (input: import("@hot-updater/plugin-core").ReleaseTarget & {
|
|
24
|
+
readonly targetChannel: string;
|
|
25
|
+
readonly action?: "copy" | "move";
|
|
26
|
+
}) => Promise<import("@hot-updater/plugin-core").PromoteReleaseResult>;
|
|
27
|
+
rebuildReleaseCatalog: (scopeKey: string) => Promise<import("@hot-updater/plugin-core").ReleaseCatalogRebuildResult>;
|
|
28
|
+
preflightReleaseCatalogRebuild: (scopeKey: string) => Promise<import("@hot-updater/plugin-core").ReleaseCatalogRebuildPreflight>;
|
|
29
|
+
ensureChannel: (name: string) => Promise<import("@hot-updater/plugin-core").ChannelRow>;
|
|
30
|
+
deleteChannel: (id: string) => Promise<import("@hot-updater/plugin-core").ChannelDeleteResult>;
|
|
31
|
+
updateBundle: (id: string, update: Partial<Omit<import("@hot-updater/core").Bundle, "id" | "patches">> & {
|
|
32
|
+
readonly patches?: import("@hot-updater/core").Bundle["patches"];
|
|
33
|
+
}) => Promise<void>;
|
|
34
|
+
deleteBundles: (ids: readonly string[]) => Promise<void>;
|
|
35
|
+
getReleaseCatalog(input: ReleaseCatalogRequest): Promise<import("@hot-updater/core").ReleaseCatalog | null>;
|
|
36
|
+
getArtifactInfo(targetBundleId: string, currentBundleId: string, artifactProtocolVersion: 1): Promise<import("@hot-updater/core").ArtifactInfo | null>;
|
|
37
|
+
getBundle(id: string): Promise<import("@hot-updater/plugin-core").BundleDetail | null>;
|
|
38
|
+
countBundleChildren(baseBundleIds: readonly string[]): Promise<Record<string, number>>;
|
|
39
|
+
listPatchesFromBase(baseBundleId: string, input: import("@hot-updater/plugin-core").KeysetInput): Promise<import("@hot-updater/plugin-core").BundlePatchRow[]>;
|
|
40
|
+
listBundles(input: import("@hot-updater/plugin-core").KeysetInput & {
|
|
41
|
+
readonly platform?: "ios" | "android";
|
|
42
|
+
}): Promise<import("@hot-updater/plugin-core").BundleDetail[]>;
|
|
43
|
+
countBundles(platform?: "ios" | "android"): Promise<number>;
|
|
44
|
+
findBaseBundleIds(candidateKey: string, bundleId: string, limit: number): Promise<string[]>;
|
|
45
|
+
getRelease(id: string): Promise<import("@hot-updater/plugin-core").ReleaseRow | null>;
|
|
46
|
+
listReleases(input: import("@hot-updater/plugin-core").KeysetInput & {
|
|
47
|
+
readonly filter: import("@hot-updater/plugin-core").ReleaseFilter;
|
|
48
|
+
}): Promise<import("@hot-updater/plugin-core").ReleaseRow[]>;
|
|
49
|
+
latestReleaseId(scopeKey: string): Promise<string | null>;
|
|
50
|
+
getReleaseCatalogRow(scopeKey: string): Promise<import("@hot-updater/plugin-core").ReleaseCatalogRow | null>;
|
|
51
|
+
listReleaseCatalogs(input: import("@hot-updater/plugin-core").KeysetInput): Promise<import("@hot-updater/plugin-core").ReleaseCatalogRow[]>;
|
|
52
|
+
listChannels(): Promise<import("@hot-updater/plugin-core").ChannelRow[]>;
|
|
53
|
+
findChannelByName(name: string): Promise<import("@hot-updater/plugin-core").ChannelRow | null>;
|
|
54
|
+
};
|
|
55
|
+
type CoreApi = ReturnType<typeof createCoreApi>;
|
|
56
|
+
/**
|
|
57
|
+
* Core's API for a configured database, as the CLI uses it: a self-hosted
|
|
58
|
+
* server's admin API when the database is `standaloneRepository`, or the
|
|
59
|
+
* database's own storage adapter, in process.
|
|
60
|
+
*/
|
|
61
|
+
declare const createDatabaseCoreApi: (database: unknown, options?: {
|
|
62
|
+
readonly now?: () => number;
|
|
63
|
+
}) => HotUpdaterCoreApi;
|
|
64
|
+
//#endregion
|
|
65
|
+
export { CoreApi, CoreApiOptions, createCoreApi, createDatabaseCoreApi };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { resolveSchema } from "../database/resolveSchema.mjs";
|
|
2
|
+
import { createDatabaseEngine } from "../database/database.mjs";
|
|
3
|
+
import { createCoreReads } from "./reads.mjs";
|
|
4
|
+
import { createCoreOperations } from "./operations.mjs";
|
|
5
|
+
import { coreModule } from "./schema.mjs";
|
|
6
|
+
//#region src/core/api.ts
|
|
7
|
+
/**
|
|
8
|
+
* The update check answers from one Release Catalog row, so a transaction
|
|
9
|
+
* changes what the cacheable client routes answer only when it writes one.
|
|
10
|
+
* The purge runs once, after the attempt that commits.
|
|
11
|
+
*/
|
|
12
|
+
const purgingCachedRoutes = (db, onCachedRoutesChange) => {
|
|
13
|
+
if (onCachedRoutesChange === void 0) return db;
|
|
14
|
+
return {
|
|
15
|
+
...db,
|
|
16
|
+
async transaction(fn) {
|
|
17
|
+
let changed = false;
|
|
18
|
+
const result = await db.transaction((tx) => {
|
|
19
|
+
changed = false;
|
|
20
|
+
return fn({
|
|
21
|
+
...tx,
|
|
22
|
+
create: (model, row) => {
|
|
23
|
+
changed ||= model === "release_catalogs";
|
|
24
|
+
tx.create(model, row);
|
|
25
|
+
},
|
|
26
|
+
update: (model, row, set) => {
|
|
27
|
+
changed ||= model === "release_catalogs";
|
|
28
|
+
tx.update(model, row, set);
|
|
29
|
+
},
|
|
30
|
+
delete: (model, row) => {
|
|
31
|
+
changed ||= model === "release_catalogs";
|
|
32
|
+
return tx.delete(model, row);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
if (changed) await onCachedRoutesChange();
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/** Core's reads and typed writes over one database handle. */
|
|
42
|
+
const createCoreApi = (db, storage, options = {}) => {
|
|
43
|
+
const reads = createCoreReads(db, storage);
|
|
44
|
+
return {
|
|
45
|
+
...reads,
|
|
46
|
+
...createCoreOperations(purgingCachedRoutes(db, options.onCachedRoutesChange), options),
|
|
47
|
+
/** One read, which checks the schema settings first. */
|
|
48
|
+
ready: async () => {
|
|
49
|
+
await reads.listReleaseCatalogs({ limit: 1 });
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Core's API in process, on a database's storage adapter: how the CLI reads
|
|
55
|
+
* and writes a database that runs on the storage engine.
|
|
56
|
+
*/
|
|
57
|
+
const createInProcessCoreApi = (adapter, options = {}) => createCoreApi(createDatabaseEngine({
|
|
58
|
+
adapter,
|
|
59
|
+
schema: resolveSchema([coreModule])
|
|
60
|
+
}).database(coreModule), { resolveFileUrl: async () => null }, options);
|
|
61
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
62
|
+
const isAdapter = (value) => isRecord(value) && [
|
|
63
|
+
"fits",
|
|
64
|
+
"get",
|
|
65
|
+
"query",
|
|
66
|
+
"write"
|
|
67
|
+
].every((method) => typeof value[method] === "function");
|
|
68
|
+
/** The storage adapter a configured database runs on, if it is on the engine. */
|
|
69
|
+
const engineAdapterOf = (database) => isRecord(database) && isAdapter(database.adapter) ? database.adapter : isAdapter(database) ? database : void 0;
|
|
70
|
+
const OFF_ENGINE_DATABASE = "This database does not run on Hot Updater's storage engine. Upgrade its provider package to 1.0.";
|
|
71
|
+
/**
|
|
72
|
+
* Core's API for a configured database, as the CLI uses it: a self-hosted
|
|
73
|
+
* server's admin API when the database is `standaloneRepository`, or the
|
|
74
|
+
* database's own storage adapter, in process.
|
|
75
|
+
*/
|
|
76
|
+
const createDatabaseCoreApi = (database, options = {}) => {
|
|
77
|
+
if (isRecord(database) && isRecord(database.core)) return database.core;
|
|
78
|
+
const adapter = engineAdapterOf(database);
|
|
79
|
+
if (adapter === void 0) throw new Error(OFF_ENGINE_DATABASE);
|
|
80
|
+
const engineDatabase = database;
|
|
81
|
+
return createInProcessCoreApi(adapter, {
|
|
82
|
+
...options,
|
|
83
|
+
...typeof engineDatabase.onCachedRoutesChange === "function" ? { onCachedRoutesChange: () => engineDatabase.onCachedRoutesChange() } : {}
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
//#endregion
|
|
87
|
+
export { OFF_ENGINE_DATABASE, createCoreApi, createDatabaseCoreApi, createInProcessCoreApi, engineAdapterOf };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const require_releaseCatalog = require("../db/releaseCatalog.cjs");
|
|
2
|
+
let _hot_updater_core = require("@hot-updater/core");
|
|
3
|
+
let verkit = require("verkit");
|
|
4
|
+
//#region src/core/baseCandidates.ts
|
|
5
|
+
/**
|
|
6
|
+
* A new bundle's base-candidate key: the Release Catalog scope its devices
|
|
7
|
+
* update from, and for an app version its normalized range; null for a
|
|
8
|
+
* target without a valid range.
|
|
9
|
+
*/
|
|
10
|
+
const targetBaseCandidateKey = (target) => {
|
|
11
|
+
const channelKey = (0, _hot_updater_core.encodeChannelKey)(target.channel);
|
|
12
|
+
if (target.fingerprintHash) return JSON.stringify([(0, _hot_updater_core.createReleaseCatalogScopeKey)({
|
|
13
|
+
channelKey,
|
|
14
|
+
fingerprintHash: target.fingerprintHash,
|
|
15
|
+
platform: target.platform,
|
|
16
|
+
strategy: "FINGERPRINT"
|
|
17
|
+
})]);
|
|
18
|
+
const range = target.appVersion === null ? null : (0, verkit.normalizeRange)(target.appVersion);
|
|
19
|
+
return range === null ? null : JSON.stringify([(0, _hot_updater_core.createReleaseCatalogScopeKey)({
|
|
20
|
+
channelKey,
|
|
21
|
+
platform: target.platform,
|
|
22
|
+
strategy: "APP_VERSION"
|
|
23
|
+
}), range]);
|
|
24
|
+
};
|
|
25
|
+
/** The scope and range a base-candidate key names; null for any other string. */
|
|
26
|
+
const parseBaseCandidateKey = (key) => {
|
|
27
|
+
try {
|
|
28
|
+
const parsed = JSON.parse(key);
|
|
29
|
+
if (!Array.isArray(parsed) || typeof parsed[0] !== "string") return null;
|
|
30
|
+
const [scopeKey, text] = parsed;
|
|
31
|
+
const { strategy } = (0, _hot_updater_core.parseReleaseCatalogScopeKey)(scopeKey);
|
|
32
|
+
if (strategy === "FINGERPRINT") return parsed.length === 1 ? {
|
|
33
|
+
scopeKey,
|
|
34
|
+
range: null
|
|
35
|
+
} : null;
|
|
36
|
+
const range = parsed.length === 2 && typeof text === "string" ? (0, verkit.normalizeRange)(text) : null;
|
|
37
|
+
return range === null ? null : {
|
|
38
|
+
scopeKey,
|
|
39
|
+
range
|
|
40
|
+
};
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/** A compiled segment as a range: its version when it holds exactly one. */
|
|
46
|
+
const segmentRange = ({ lower, upper }) => lower?.inclusive && upper?.inclusive && lower.version === upper.version ? lower.version : [lower === null ? "" : `${lower.inclusive ? ">=" : ">"}${lower.version}`, upper === null ? "" : `${upper.inclusive ? "<=" : "<"}${upper.version}`].join(" ").trim() || "*";
|
|
47
|
+
/**
|
|
48
|
+
* Auto-patch bases from a scope's compiled Release Catalog, which holds
|
|
49
|
+
* every enabled bundle release of the scope: those whose range intersects
|
|
50
|
+
* `range` (all of them in a fingerprint scope), newest release first, each
|
|
51
|
+
* bundle once and older than `bundleId`, at most `limit`.
|
|
52
|
+
*/
|
|
53
|
+
const baseBundleIdsOf = (row, range, bundleId, limit) => {
|
|
54
|
+
const catalog = require_releaseCatalog.parseCompiledCatalog(row.payload, row.strategy);
|
|
55
|
+
const serving = new Set(catalog.strategy === "FINGERPRINT" ? catalog.rollbackReleaseIndexes : catalog.segments.flatMap((segment) => range !== null && (0, verkit.rangesIntersect)(range, segmentRange(segment)) ? segment.rollbackReleaseIndexes : []));
|
|
56
|
+
const newestFirst = catalog.releaseDescriptors.map((descriptor, index) => ({
|
|
57
|
+
descriptor,
|
|
58
|
+
index
|
|
59
|
+
})).sort((left, right) => left.descriptor.releaseId < right.descriptor.releaseId ? 1 : -1);
|
|
60
|
+
const ids = [];
|
|
61
|
+
for (const { descriptor, index } of newestFirst) {
|
|
62
|
+
if (ids.length >= limit) break;
|
|
63
|
+
const id = descriptor.bundleId;
|
|
64
|
+
if (serving.has(index) && descriptor.kind === "BUNDLE" && id !== null && id < bundleId && !ids.includes(id)) ids.push(id);
|
|
65
|
+
}
|
|
66
|
+
return ids;
|
|
67
|
+
};
|
|
68
|
+
//#endregion
|
|
69
|
+
exports.baseBundleIdsOf = baseBundleIdsOf;
|
|
70
|
+
exports.parseBaseCandidateKey = parseBaseCandidateKey;
|
|
71
|
+
exports.targetBaseCandidateKey = targetBaseCandidateKey;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ReleaseCatalogRow } from "@hot-updater/plugin-core";
|
|
2
|
+
//#region src/core/baseCandidates.d.ts
|
|
3
|
+
/** A new bundle's auto-patch target: where it is released, and to whom. */
|
|
4
|
+
interface BaseCandidateTarget {
|
|
5
|
+
readonly channel: string;
|
|
6
|
+
readonly platform: "ios" | "android";
|
|
7
|
+
readonly fingerprintHash: string | null;
|
|
8
|
+
readonly appVersion: string | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A new bundle's base-candidate key: the Release Catalog scope its devices
|
|
12
|
+
* update from, and for an app version its normalized range; null for a
|
|
13
|
+
* target without a valid range.
|
|
14
|
+
*/
|
|
15
|
+
declare const targetBaseCandidateKey: (target: BaseCandidateTarget) => string | null;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { BaseCandidateTarget, targetBaseCandidateKey };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ReleaseCatalogRow } from "@hot-updater/plugin-core";
|
|
2
|
+
//#region src/core/baseCandidates.d.ts
|
|
3
|
+
/** A new bundle's auto-patch target: where it is released, and to whom. */
|
|
4
|
+
interface BaseCandidateTarget {
|
|
5
|
+
readonly channel: string;
|
|
6
|
+
readonly platform: "ios" | "android";
|
|
7
|
+
readonly fingerprintHash: string | null;
|
|
8
|
+
readonly appVersion: string | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A new bundle's base-candidate key: the Release Catalog scope its devices
|
|
12
|
+
* update from, and for an app version its normalized range; null for a
|
|
13
|
+
* target without a valid range.
|
|
14
|
+
*/
|
|
15
|
+
declare const targetBaseCandidateKey: (target: BaseCandidateTarget) => string | null;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { BaseCandidateTarget, targetBaseCandidateKey };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { parseCompiledCatalog } from "../db/releaseCatalog.mjs";
|
|
2
|
+
import { createReleaseCatalogScopeKey, encodeChannelKey, parseReleaseCatalogScopeKey } from "@hot-updater/core";
|
|
3
|
+
import { normalizeRange, rangesIntersect } from "verkit";
|
|
4
|
+
//#region src/core/baseCandidates.ts
|
|
5
|
+
/**
|
|
6
|
+
* A new bundle's base-candidate key: the Release Catalog scope its devices
|
|
7
|
+
* update from, and for an app version its normalized range; null for a
|
|
8
|
+
* target without a valid range.
|
|
9
|
+
*/
|
|
10
|
+
const targetBaseCandidateKey = (target) => {
|
|
11
|
+
const channelKey = encodeChannelKey(target.channel);
|
|
12
|
+
if (target.fingerprintHash) return JSON.stringify([createReleaseCatalogScopeKey({
|
|
13
|
+
channelKey,
|
|
14
|
+
fingerprintHash: target.fingerprintHash,
|
|
15
|
+
platform: target.platform,
|
|
16
|
+
strategy: "FINGERPRINT"
|
|
17
|
+
})]);
|
|
18
|
+
const range = target.appVersion === null ? null : normalizeRange(target.appVersion);
|
|
19
|
+
return range === null ? null : JSON.stringify([createReleaseCatalogScopeKey({
|
|
20
|
+
channelKey,
|
|
21
|
+
platform: target.platform,
|
|
22
|
+
strategy: "APP_VERSION"
|
|
23
|
+
}), range]);
|
|
24
|
+
};
|
|
25
|
+
/** The scope and range a base-candidate key names; null for any other string. */
|
|
26
|
+
const parseBaseCandidateKey = (key) => {
|
|
27
|
+
try {
|
|
28
|
+
const parsed = JSON.parse(key);
|
|
29
|
+
if (!Array.isArray(parsed) || typeof parsed[0] !== "string") return null;
|
|
30
|
+
const [scopeKey, text] = parsed;
|
|
31
|
+
const { strategy } = parseReleaseCatalogScopeKey(scopeKey);
|
|
32
|
+
if (strategy === "FINGERPRINT") return parsed.length === 1 ? {
|
|
33
|
+
scopeKey,
|
|
34
|
+
range: null
|
|
35
|
+
} : null;
|
|
36
|
+
const range = parsed.length === 2 && typeof text === "string" ? normalizeRange(text) : null;
|
|
37
|
+
return range === null ? null : {
|
|
38
|
+
scopeKey,
|
|
39
|
+
range
|
|
40
|
+
};
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/** A compiled segment as a range: its version when it holds exactly one. */
|
|
46
|
+
const segmentRange = ({ lower, upper }) => lower?.inclusive && upper?.inclusive && lower.version === upper.version ? lower.version : [lower === null ? "" : `${lower.inclusive ? ">=" : ">"}${lower.version}`, upper === null ? "" : `${upper.inclusive ? "<=" : "<"}${upper.version}`].join(" ").trim() || "*";
|
|
47
|
+
/**
|
|
48
|
+
* Auto-patch bases from a scope's compiled Release Catalog, which holds
|
|
49
|
+
* every enabled bundle release of the scope: those whose range intersects
|
|
50
|
+
* `range` (all of them in a fingerprint scope), newest release first, each
|
|
51
|
+
* bundle once and older than `bundleId`, at most `limit`.
|
|
52
|
+
*/
|
|
53
|
+
const baseBundleIdsOf = (row, range, bundleId, limit) => {
|
|
54
|
+
const catalog = parseCompiledCatalog(row.payload, row.strategy);
|
|
55
|
+
const serving = new Set(catalog.strategy === "FINGERPRINT" ? catalog.rollbackReleaseIndexes : catalog.segments.flatMap((segment) => range !== null && rangesIntersect(range, segmentRange(segment)) ? segment.rollbackReleaseIndexes : []));
|
|
56
|
+
const newestFirst = catalog.releaseDescriptors.map((descriptor, index) => ({
|
|
57
|
+
descriptor,
|
|
58
|
+
index
|
|
59
|
+
})).sort((left, right) => left.descriptor.releaseId < right.descriptor.releaseId ? 1 : -1);
|
|
60
|
+
const ids = [];
|
|
61
|
+
for (const { descriptor, index } of newestFirst) {
|
|
62
|
+
if (ids.length >= limit) break;
|
|
63
|
+
const id = descriptor.bundleId;
|
|
64
|
+
if (serving.has(index) && descriptor.kind === "BUNDLE" && id !== null && id < bundleId && !ids.includes(id)) ids.push(id);
|
|
65
|
+
}
|
|
66
|
+
return ids;
|
|
67
|
+
};
|
|
68
|
+
//#endregion
|
|
69
|
+
export { baseBundleIdsOf, parseBaseCandidateKey, targetBaseCandidateKey };
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
const require_errors = require("../database/errors.cjs");
|
|
2
|
+
const require_reads = require("./reads.cjs");
|
|
3
|
+
const require_writes = require("./writes.cjs");
|
|
4
|
+
const require_releases = require("./releases.cjs");
|
|
5
|
+
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
6
|
+
let _hot_updater_plugin_core_internal = require("@hot-updater/plugin-core/internal");
|
|
7
|
+
let _hot_updater_core = require("@hot-updater/core");
|
|
8
|
+
//#region src/core/operations.ts
|
|
9
|
+
/** Carries a preflight's result out of the transaction it stops, so nothing is written. */
|
|
10
|
+
var Preflight = class extends Error {
|
|
11
|
+
result;
|
|
12
|
+
constructor(result) {
|
|
13
|
+
super("preflight");
|
|
14
|
+
this.result = result;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const dryRun = async (db, read) => {
|
|
18
|
+
try {
|
|
19
|
+
await db.transaction(async (tx) => {
|
|
20
|
+
throw new Preflight(await read(tx));
|
|
21
|
+
});
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if (error instanceof Preflight) return error.result;
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
throw new Error("A preflight transaction returned without its result.");
|
|
27
|
+
};
|
|
28
|
+
/** A channel's catalog scope for a platform, and a fingerprint when it has one. */
|
|
29
|
+
const scopeOf = (channel, platform, fingerprintHash) => {
|
|
30
|
+
const channelKey = (0, _hot_updater_core.encodeChannelKey)(channel.name);
|
|
31
|
+
return fingerprintHash === null ? {
|
|
32
|
+
channelId: channel.id,
|
|
33
|
+
channelName: channel.name,
|
|
34
|
+
fingerprintHash,
|
|
35
|
+
platform,
|
|
36
|
+
scopeKey: (0, _hot_updater_core.createReleaseCatalogScopeKey)({
|
|
37
|
+
channelKey,
|
|
38
|
+
platform,
|
|
39
|
+
strategy: "APP_VERSION"
|
|
40
|
+
}),
|
|
41
|
+
strategy: "APP_VERSION"
|
|
42
|
+
} : {
|
|
43
|
+
channelId: channel.id,
|
|
44
|
+
channelName: channel.name,
|
|
45
|
+
fingerprintHash,
|
|
46
|
+
platform,
|
|
47
|
+
scopeKey: (0, _hot_updater_core.createReleaseCatalogScopeKey)({
|
|
48
|
+
channelKey,
|
|
49
|
+
fingerprintHash,
|
|
50
|
+
platform,
|
|
51
|
+
strategy: "FINGERPRINT"
|
|
52
|
+
}),
|
|
53
|
+
strategy: "FINGERPRINT"
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
/** A release and its scope, checked against the revision the caller saw. */
|
|
57
|
+
const loadTarget = async (tx, { releaseId, expectedRevision }) => {
|
|
58
|
+
const row = await tx.findOne("releases", { id: releaseId });
|
|
59
|
+
if (row === null) throw new _hot_updater_plugin_core.ReleaseManagementError("RELEASE_NOT_FOUND", `Release "${releaseId}" was not found.`);
|
|
60
|
+
const release = require_reads.toReleaseRow(row);
|
|
61
|
+
if (expectedRevision !== void 0 && expectedRevision !== release.revision) throw new _hot_updater_plugin_core.ReleaseManagementError("VERSION_CONFLICT", `Release "${release.id}" is revision ${release.revision}; expected ${expectedRevision}.`);
|
|
62
|
+
const catalog = await tx.findOne("release_catalogs", { scope_key: release.scope_key });
|
|
63
|
+
if (catalog === null) throw new _hot_updater_plugin_core.ReleaseCatalogMutationError("INVALID_SCOPE", `Release "${release.id}" has no catalog projection.`);
|
|
64
|
+
return {
|
|
65
|
+
release,
|
|
66
|
+
scope: {
|
|
67
|
+
channelId: release.channel_id,
|
|
68
|
+
channelName: (0, _hot_updater_core.decodeChannelKey)(catalog.channel_key),
|
|
69
|
+
fingerprintHash: release.fingerprint_hash,
|
|
70
|
+
platform: release.platform,
|
|
71
|
+
scopeKey: release.scope_key,
|
|
72
|
+
strategy: release.strategy
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
const policyUpdate = (release, patch, updatedAtMs) => {
|
|
77
|
+
if (patch.fingerprintHash !== void 0 && patch.fingerprintHash !== release.fingerprint_hash) throw new _hot_updater_plugin_core.ReleaseManagementError("SCOPE_MOVE_UNSUPPORTED", "Changing a fingerprint target requires an atomic Release scope move.");
|
|
78
|
+
return {
|
|
79
|
+
...patch.enabled === void 0 ? {} : { enabled: patch.enabled },
|
|
80
|
+
...patch.message === void 0 ? {} : { message: patch.message },
|
|
81
|
+
...patch.rolloutCohortCount === void 0 ? {} : { rollout_cohort_count: patch.rolloutCohortCount },
|
|
82
|
+
...patch.shouldForceUpdate === void 0 ? {} : { should_force_update: patch.shouldForceUpdate },
|
|
83
|
+
...patch.targetAppVersion === void 0 ? {} : { target_app_version: patch.targetAppVersion },
|
|
84
|
+
...patch.targetCohorts === void 0 ? {} : { target_cohorts: [...patch.targetCohorts] },
|
|
85
|
+
updated_at_ms: updatedAtMs
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
const mutationResult = ({ catalog, release }) => ({
|
|
89
|
+
attempts: 1,
|
|
90
|
+
catalog,
|
|
91
|
+
release
|
|
92
|
+
});
|
|
93
|
+
/** The scope a catalog row names, for a rebuild. */
|
|
94
|
+
const catalogScope = async (tx, scopeKey) => {
|
|
95
|
+
const row = await tx.findOne("release_catalogs", { scope_key: scopeKey });
|
|
96
|
+
if (row === null) throw new Error(`Release catalog "${scopeKey}" was not found.`);
|
|
97
|
+
return {
|
|
98
|
+
channelId: row.channel_id,
|
|
99
|
+
channelName: (0, _hot_updater_core.decodeChannelKey)(row.channel_key),
|
|
100
|
+
fingerprintHash: row.fingerprint_hash,
|
|
101
|
+
platform: row.platform,
|
|
102
|
+
scopeKey: row.scope_key,
|
|
103
|
+
strategy: row.strategy
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Core's typed writes: each runs in one engine transaction rooted at the
|
|
108
|
+
* catalogs it changes, so a concurrent change reruns it instead of
|
|
109
|
+
* publishing a stale catalog.
|
|
110
|
+
*/
|
|
111
|
+
const createCoreOperations = (db, { now = Date.now } = {}) => {
|
|
112
|
+
const ensureChannel = async (name) => (await require_writes.insertChannel(db, {
|
|
113
|
+
id: `channel:${(0, _hot_updater_core.encodeChannelKey)(name)}`,
|
|
114
|
+
name
|
|
115
|
+
})).row;
|
|
116
|
+
/**
|
|
117
|
+
* Runs a write that ensured its channels first. A channel deleted between
|
|
118
|
+
* that and the write refuses the write, so it runs again and ensures it anew.
|
|
119
|
+
*/
|
|
120
|
+
const withChannels = async (write) => {
|
|
121
|
+
for (let attempt = 1;; attempt += 1) try {
|
|
122
|
+
return await write();
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if (attempt < 3 && error instanceof require_errors.DatabaseConstraintError && error.reason === "not_found" && error.model === "channels") continue;
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
const deployOnce = async (deployments) => {
|
|
129
|
+
const channels = /* @__PURE__ */ new Map();
|
|
130
|
+
for (const { release } of deployments) if (!channels.has(release.channel)) channels.set(release.channel, await ensureChannel(release.channel));
|
|
131
|
+
const platforms = /* @__PURE__ */ new Map();
|
|
132
|
+
for (const deployment of deployments) {
|
|
133
|
+
if (!("bundleId" in deployment) || platforms.has(deployment.bundleId)) continue;
|
|
134
|
+
const row = await db.findOne("bundles", { id: deployment.bundleId });
|
|
135
|
+
if (row === null) throw new _hot_updater_plugin_core.DatabaseBundleNotFoundError(deployment.bundleId);
|
|
136
|
+
platforms.set(deployment.bundleId, require_reads.toBundleRow(row).platform);
|
|
137
|
+
}
|
|
138
|
+
const updatedAtMs = now();
|
|
139
|
+
return (await require_releases.changeReleases(db, deployments.map((deployment) => {
|
|
140
|
+
const { release: policy } = deployment;
|
|
141
|
+
const stored = "bundleId" in deployment;
|
|
142
|
+
const bundleId = stored ? deployment.bundleId : deployment.bundle.id;
|
|
143
|
+
const platform = stored ? platforms.get(deployment.bundleId) : deployment.bundle.platform;
|
|
144
|
+
const scope = scopeOf(channels.get(policy.channel), platform, policy.fingerprintHash);
|
|
145
|
+
return {
|
|
146
|
+
scope,
|
|
147
|
+
...stored ? {} : { bundle: {
|
|
148
|
+
row: (0, _hot_updater_plugin_core.bundleToRow)(deployment.bundle),
|
|
149
|
+
patches: (0, _hot_updater_plugin_core.bundleToPatchRows)(deployment.bundle)
|
|
150
|
+
} },
|
|
151
|
+
change: {
|
|
152
|
+
operation: "insert",
|
|
153
|
+
row: {
|
|
154
|
+
bundle_id: bundleId,
|
|
155
|
+
channel_id: scope.channelId,
|
|
156
|
+
created_at_ms: updatedAtMs,
|
|
157
|
+
enabled: policy.enabled,
|
|
158
|
+
fingerprint_hash: policy.fingerprintHash,
|
|
159
|
+
kind: "BUNDLE",
|
|
160
|
+
message: policy.message,
|
|
161
|
+
operation: "DEPLOY",
|
|
162
|
+
platform,
|
|
163
|
+
revision: 1,
|
|
164
|
+
rollout_cohort_count: policy.rolloutCohortCount ?? 1e3,
|
|
165
|
+
scope_key: scope.scopeKey,
|
|
166
|
+
should_force_update: policy.shouldForceUpdate,
|
|
167
|
+
source_release_id: null,
|
|
168
|
+
strategy: scope.strategy,
|
|
169
|
+
target_app_version: policy.targetAppVersion,
|
|
170
|
+
target_cohorts: policy.targetCohorts ?? [],
|
|
171
|
+
updated_at_ms: updatedAtMs
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
updatedAtMs
|
|
175
|
+
};
|
|
176
|
+
}))).map(mutationResult);
|
|
177
|
+
};
|
|
178
|
+
return {
|
|
179
|
+
deploy: (deployments) => withChannels(() => deployOnce(deployments)),
|
|
180
|
+
updateReleasePolicy: (input) => {
|
|
181
|
+
const updatedAtMs = now();
|
|
182
|
+
return db.transaction(async (tx) => {
|
|
183
|
+
const { release, scope } = await loadTarget(tx, input);
|
|
184
|
+
return mutationResult(await require_releases.changeRelease(tx, {
|
|
185
|
+
scope,
|
|
186
|
+
change: {
|
|
187
|
+
operation: "update",
|
|
188
|
+
id: release.id,
|
|
189
|
+
update: policyUpdate(release, input.patch, updatedAtMs)
|
|
190
|
+
},
|
|
191
|
+
updatedAtMs
|
|
192
|
+
}));
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
preflightReleasePolicy: (input) => {
|
|
196
|
+
const updatedAtMs = now();
|
|
197
|
+
return dryRun(db, async (tx) => {
|
|
198
|
+
const { release, scope } = await loadTarget(tx, input);
|
|
199
|
+
const stored = await require_releases.readCatalog(tx, scope.scopeKey);
|
|
200
|
+
const changed = await require_releases.changeRelease(tx, {
|
|
201
|
+
scope,
|
|
202
|
+
change: {
|
|
203
|
+
operation: "update",
|
|
204
|
+
id: release.id,
|
|
205
|
+
update: policyUpdate(release, input.patch, updatedAtMs)
|
|
206
|
+
},
|
|
207
|
+
updatedAtMs
|
|
208
|
+
});
|
|
209
|
+
return {
|
|
210
|
+
catalog: changed.catalog,
|
|
211
|
+
currentCatalog: stored.catalog,
|
|
212
|
+
diagnostics: changed.diagnostics,
|
|
213
|
+
expectedReleaseRevision: release.revision,
|
|
214
|
+
release: changed.release
|
|
215
|
+
};
|
|
216
|
+
});
|
|
217
|
+
},
|
|
218
|
+
deleteRelease: (input) => db.transaction(async (tx) => {
|
|
219
|
+
const { release, scope } = await loadTarget(tx, input);
|
|
220
|
+
if (release.enabled) throw new _hot_updater_plugin_core.ReleaseManagementError("ENABLED_RELEASE", `Disable Release "${release.id}" before hard deletion.`);
|
|
221
|
+
return mutationResult(await require_releases.changeRelease(tx, {
|
|
222
|
+
scope,
|
|
223
|
+
change: {
|
|
224
|
+
operation: "delete",
|
|
225
|
+
id: release.id
|
|
226
|
+
},
|
|
227
|
+
updatedAtMs: now()
|
|
228
|
+
}));
|
|
229
|
+
}),
|
|
230
|
+
promoteRelease: (input) => withChannels(async () => {
|
|
231
|
+
const checkSource = (source) => {
|
|
232
|
+
if (source.kind !== "BUNDLE" || source.bundle_id === null) throw new _hot_updater_plugin_core.ReleaseManagementError("TARGET_RELEASE_INVALID", "Only a Bundle Release can be promoted.");
|
|
233
|
+
};
|
|
234
|
+
checkSource((await db.transaction((tx) => loadTarget(tx, input))).release);
|
|
235
|
+
const targetChannel = input.targetChannel.trim();
|
|
236
|
+
if (targetChannel.length === 0) throw new _hot_updater_plugin_core.ReleaseManagementError("TARGET_RELEASE_INVALID", "Promotion requires a target channel.");
|
|
237
|
+
const channel = await ensureChannel(targetChannel);
|
|
238
|
+
const updatedAtMs = now();
|
|
239
|
+
return db.transaction(async (tx) => {
|
|
240
|
+
const { release: source, scope: sourceScope } = await loadTarget(tx, input);
|
|
241
|
+
checkSource(source);
|
|
242
|
+
const targetScope = scopeOf(channel, source.platform, source.fingerprint_hash);
|
|
243
|
+
if (targetScope.scopeKey === sourceScope.scopeKey) throw new _hot_updater_plugin_core.ReleaseManagementError("TARGET_RELEASE_INVALID", "Source and target Release scopes are the same.");
|
|
244
|
+
const { rows } = await tx.findMany("releases", {
|
|
245
|
+
index: "byScope",
|
|
246
|
+
where: { scope_key: targetScope.scopeKey },
|
|
247
|
+
order: "desc",
|
|
248
|
+
limit: 1
|
|
249
|
+
});
|
|
250
|
+
const floor = [
|
|
251
|
+
rows[0]?.id ?? null,
|
|
252
|
+
source.id,
|
|
253
|
+
source.bundle_id
|
|
254
|
+
].filter((id) => id !== null && (0, _hot_updater_plugin_core.isUUIDv7)(id)).sort().at(-1);
|
|
255
|
+
const moved = input.action === "move" ? await require_releases.changeRelease(tx, {
|
|
256
|
+
scope: sourceScope,
|
|
257
|
+
change: {
|
|
258
|
+
operation: "update",
|
|
259
|
+
id: source.id,
|
|
260
|
+
update: {
|
|
261
|
+
enabled: false,
|
|
262
|
+
updated_at_ms: updatedAtMs
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
updatedAtMs
|
|
266
|
+
}) : null;
|
|
267
|
+
const target = await require_releases.changeRelease(tx, {
|
|
268
|
+
scope: targetScope,
|
|
269
|
+
change: {
|
|
270
|
+
operation: "insert",
|
|
271
|
+
row: {
|
|
272
|
+
...source,
|
|
273
|
+
id: (0, _hot_updater_plugin_core.createUUIDv7After)(floor ?? null, updatedAtMs),
|
|
274
|
+
revision: 1,
|
|
275
|
+
scope_key: targetScope.scopeKey,
|
|
276
|
+
channel_id: targetScope.channelId,
|
|
277
|
+
enabled: true,
|
|
278
|
+
rollout_cohort_count: 1e3,
|
|
279
|
+
target_cohorts: [],
|
|
280
|
+
operation: "PROMOTE",
|
|
281
|
+
source_release_id: source.id,
|
|
282
|
+
created_at_ms: updatedAtMs,
|
|
283
|
+
updated_at_ms: updatedAtMs
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
updatedAtMs
|
|
287
|
+
});
|
|
288
|
+
return {
|
|
289
|
+
source: moved === null ? null : mutationResult(moved),
|
|
290
|
+
target: mutationResult(target)
|
|
291
|
+
};
|
|
292
|
+
});
|
|
293
|
+
}),
|
|
294
|
+
rebuildReleaseCatalog: (scopeKey) => {
|
|
295
|
+
const updatedAtMs = now();
|
|
296
|
+
return db.transaction(async (tx) => {
|
|
297
|
+
const { current: _current, ...rebuilt } = await require_releases.rebuildScope(tx, await catalogScope(tx, scopeKey), updatedAtMs);
|
|
298
|
+
return {
|
|
299
|
+
attempts: 1,
|
|
300
|
+
...rebuilt
|
|
301
|
+
};
|
|
302
|
+
});
|
|
303
|
+
},
|
|
304
|
+
preflightReleaseCatalogRebuild: (scopeKey) => {
|
|
305
|
+
const updatedAtMs = now();
|
|
306
|
+
return dryRun(db, async (tx) => {
|
|
307
|
+
const rebuilt = await require_releases.rebuildScope(tx, await catalogScope(tx, scopeKey), updatedAtMs);
|
|
308
|
+
return {
|
|
309
|
+
changed: rebuilt.changed,
|
|
310
|
+
currentCatalog: rebuilt.current,
|
|
311
|
+
diagnostics: rebuilt.diagnostics,
|
|
312
|
+
projectedCatalog: rebuilt.catalog
|
|
313
|
+
};
|
|
314
|
+
});
|
|
315
|
+
},
|
|
316
|
+
ensureChannel,
|
|
317
|
+
deleteChannel: (id) => require_writes.deleteChannel(db, id),
|
|
318
|
+
updateBundle: (id, update) => db.transaction(async (tx) => {
|
|
319
|
+
const current = await tx.findOne("bundles", { id });
|
|
320
|
+
if (current === null) throw new _hot_updater_plugin_core.DatabaseBundleNotFoundError(id);
|
|
321
|
+
const { patches, ...fields } = update;
|
|
322
|
+
const next = {
|
|
323
|
+
...(0, _hot_updater_plugin_core.rowToBundle)(require_reads.toBundleRow(current)),
|
|
324
|
+
...fields,
|
|
325
|
+
id
|
|
326
|
+
};
|
|
327
|
+
const { id: _id, ...set } = (0, _hot_updater_plugin_core.bundleToRow)(next);
|
|
328
|
+
require_writes.updateBundle(tx, current, set);
|
|
329
|
+
if (patches !== void 0) await require_writes.replaceBundlePatches(tx, current, (0, _hot_updater_plugin_core.bundleToPatchRows)({
|
|
330
|
+
...next,
|
|
331
|
+
patches
|
|
332
|
+
}));
|
|
333
|
+
}),
|
|
334
|
+
deleteBundles: async (ids) => {
|
|
335
|
+
try {
|
|
336
|
+
await db.transaction(async (tx) => {
|
|
337
|
+
for (const id of new Set(ids)) {
|
|
338
|
+
const current = await tx.findOne("bundles", { id });
|
|
339
|
+
if (current !== null) await require_writes.deleteBundle(tx, current);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
} catch (error) {
|
|
343
|
+
if (error instanceof require_errors.DatabaseConstraintError && error.reason === "referenced") throw new _hot_updater_plugin_core_internal.DatabaseRowReferencedError();
|
|
344
|
+
throw error;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
};
|
|
349
|
+
//#endregion
|
|
350
|
+
exports.createCoreOperations = createCoreOperations;
|