@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
package/src/db/index.spec.ts
CHANGED
|
@@ -2,10 +2,8 @@ import { PGlite } from "@electric-sql/pglite";
|
|
|
2
2
|
import type { Bundle } from "@hot-updater/core";
|
|
3
3
|
import { NIL_UUID } from "@hot-updater/core";
|
|
4
4
|
import { createStoragePlugin } from "@hot-updater/plugin-core";
|
|
5
|
-
import { sql } from "drizzle-orm";
|
|
6
5
|
import { Kysely } from "kysely";
|
|
7
6
|
import { PGliteDialect } from "kysely-pglite-dialect";
|
|
8
|
-
import { type ClientSession, MongoClient } from "mongodb";
|
|
9
7
|
import {
|
|
10
8
|
afterAll,
|
|
11
9
|
afterEach,
|
|
@@ -17,143 +15,24 @@ import {
|
|
|
17
15
|
vi,
|
|
18
16
|
} from "vitest";
|
|
19
17
|
|
|
20
|
-
import { createInMemoryDatabasePlugin } from "../../../test-utils/test/inMemoryDatabasePlugin";
|
|
21
18
|
import { drizzleAdapter } from "../adapters/drizzle";
|
|
22
19
|
import { kyselyAdapter } from "../adapters/kysely";
|
|
23
|
-
import { mongoAdapter } from "../adapters/mongodb";
|
|
24
20
|
import { prismaAdapter } from "../adapters/prisma";
|
|
21
|
+
import { HotUpdaterSchemaMigrationRequiredError } from "../database/fence";
|
|
25
22
|
import {
|
|
26
23
|
createHotUpdater as createRuntimeHotUpdater,
|
|
27
24
|
type CreateHotUpdaterOptions,
|
|
28
25
|
} from "../index";
|
|
29
|
-
import { bundleToRow } from "./bundleRows";
|
|
30
|
-
import { createTableSql, hotUpdaterSchemaVersions } from "./hotUpdaterSchema";
|
|
31
26
|
import { createMigrator, generateSchema } from "./index";
|
|
32
|
-
import { generateDrizzleSchema } from "./schemaGenerators";
|
|
33
|
-
import type { DatabasePlugin, ORMProvider } from "./types";
|
|
34
27
|
|
|
35
28
|
const createHotUpdater = (
|
|
36
29
|
options: Omit<CreateHotUpdaterOptions, "clientAccess">,
|
|
37
30
|
) =>
|
|
38
31
|
createRuntimeHotUpdater({
|
|
39
32
|
...options,
|
|
40
|
-
clientAccess:
|
|
33
|
+
clientAccess: "public",
|
|
41
34
|
});
|
|
42
35
|
|
|
43
|
-
const RAW_PRISMA_SCHEMA = `model bundles {
|
|
44
|
-
id String @id
|
|
45
|
-
platform String
|
|
46
|
-
should_force_update Boolean
|
|
47
|
-
enabled Boolean
|
|
48
|
-
file_hash String
|
|
49
|
-
git_commit_hash String?
|
|
50
|
-
message String?
|
|
51
|
-
channel String @default("production")
|
|
52
|
-
storage_uri String
|
|
53
|
-
target_app_version String?
|
|
54
|
-
fingerprint_hash String?
|
|
55
|
-
metadata Json
|
|
56
|
-
manifest_storage_uri String?
|
|
57
|
-
manifest_file_hash String?
|
|
58
|
-
asset_base_storage_uri String?
|
|
59
|
-
rollout_cohort_count Int @default(1000)
|
|
60
|
-
target_cohorts Json?
|
|
61
|
-
}
|
|
62
|
-
model bundle_patches {
|
|
63
|
-
id String @id
|
|
64
|
-
bundle_id String
|
|
65
|
-
base_bundle_id String
|
|
66
|
-
base_file_hash String
|
|
67
|
-
patch_file_hash String
|
|
68
|
-
patch_storage_uri String
|
|
69
|
-
order_index Int @default(0)
|
|
70
|
-
bundle bundles @relation("bundle_patches_bundles_patches", fields: [bundle_id], references: [id], onUpdate: Restrict, onDelete: Cascade)
|
|
71
|
-
baseBundle bundles @relation("bundle_patches_bundles_baseForPatches", fields: [base_bundle_id], references: [id], onUpdate: Restrict, onDelete: Cascade)
|
|
72
|
-
}
|
|
73
|
-
model private_hot_updater_settings {
|
|
74
|
-
key String @id
|
|
75
|
-
value String @default("0.36.0")
|
|
76
|
-
}`;
|
|
77
|
-
|
|
78
|
-
const RAW_DRIZZLE_SCHEMA = `import { relations } from "drizzle-orm";
|
|
79
|
-
import {
|
|
80
|
-
pgTable,
|
|
81
|
-
uuid,
|
|
82
|
-
text,
|
|
83
|
-
boolean,
|
|
84
|
-
json,
|
|
85
|
-
integer,
|
|
86
|
-
varchar,
|
|
87
|
-
foreignKey,
|
|
88
|
-
} from "drizzle-orm/pg-core";
|
|
89
|
-
|
|
90
|
-
export const bundles = pgTable("bundles", {
|
|
91
|
-
id: uuid("id").primaryKey().notNull(),
|
|
92
|
-
platform: text("platform").notNull(),
|
|
93
|
-
should_force_update: boolean("should_force_update").notNull(),
|
|
94
|
-
enabled: boolean("enabled").notNull(),
|
|
95
|
-
file_hash: text("file_hash").notNull(),
|
|
96
|
-
git_commit_hash: text("git_commit_hash"),
|
|
97
|
-
message: text("message"),
|
|
98
|
-
channel: text("channel").notNull().default("production"),
|
|
99
|
-
storage_uri: text("storage_uri").notNull(),
|
|
100
|
-
target_app_version: text("target_app_version"),
|
|
101
|
-
fingerprint_hash: text("fingerprint_hash"),
|
|
102
|
-
metadata: json("metadata").notNull(),
|
|
103
|
-
manifest_storage_uri: text("manifest_storage_uri"),
|
|
104
|
-
manifest_file_hash: text("manifest_file_hash"),
|
|
105
|
-
asset_base_storage_uri: text("asset_base_storage_uri"),
|
|
106
|
-
rollout_cohort_count: integer("rollout_cohort_count")
|
|
107
|
-
.notNull()
|
|
108
|
-
.default(1000),
|
|
109
|
-
target_cohorts: json("target_cohorts"),
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
export const bundle_patches = pgTable(
|
|
113
|
-
"bundle_patches",
|
|
114
|
-
{
|
|
115
|
-
id: varchar("id", { length: 255 }).primaryKey().notNull(),
|
|
116
|
-
bundle_id: uuid("bundle_id").notNull(),
|
|
117
|
-
base_bundle_id: uuid("base_bundle_id").notNull(),
|
|
118
|
-
base_file_hash: text("base_file_hash").notNull(),
|
|
119
|
-
patch_file_hash: text("patch_file_hash").notNull(),
|
|
120
|
-
patch_storage_uri: text("patch_storage_uri").notNull(),
|
|
121
|
-
order_index: integer("order_index").notNull().default(0),
|
|
122
|
-
}, (table) => [
|
|
123
|
-
foreignKey({
|
|
124
|
-
columns: [table.bundle_id],
|
|
125
|
-
foreignColumns: [bundles.id],
|
|
126
|
-
name: "bundle_patches_bundle_id_fk",
|
|
127
|
-
})
|
|
128
|
-
.onUpdate("restrict")
|
|
129
|
-
.onDelete("cascade"),
|
|
130
|
-
foreignKey({
|
|
131
|
-
columns: [table.base_bundle_id],
|
|
132
|
-
foreignColumns: [bundles.id],
|
|
133
|
-
name: "bundle_patches_base_bundle_id_fk",
|
|
134
|
-
})
|
|
135
|
-
.onUpdate("restrict")
|
|
136
|
-
.onDelete("cascade"),
|
|
137
|
-
])
|
|
138
|
-
|
|
139
|
-
export const private_hot_updater_settings = pgTable("private_hot_updater_settings", {
|
|
140
|
-
key: varchar("key", { length: 255 }).primaryKey().notNull(),
|
|
141
|
-
version: varchar("version", { length: 255 }).notNull().default("0.36.0"),
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
export const bundle_patchesRelations = relations(bundle_patches, ({ one, many }) => ({
|
|
145
|
-
bundle: one(bundles, {
|
|
146
|
-
relationName: "bundle_patches_bundles_patches",
|
|
147
|
-
fields: [bundle_patches.bundle_id],
|
|
148
|
-
references: [bundles.id],
|
|
149
|
-
}),
|
|
150
|
-
baseBundle: one(bundles, {
|
|
151
|
-
relationName: "bundle_patches_bundles_baseForPatches",
|
|
152
|
-
fields: [bundle_patches.base_bundle_id],
|
|
153
|
-
references: [bundles.id],
|
|
154
|
-
}),
|
|
155
|
-
}));`;
|
|
156
|
-
|
|
157
36
|
function createTestStoragePlugin(
|
|
158
37
|
protocol: string,
|
|
159
38
|
readText: (storageUri: string) => Promise<string | null> = async () => null,
|
|
@@ -182,38 +61,6 @@ function createTestStoragePlugin(
|
|
|
182
61
|
});
|
|
183
62
|
}
|
|
184
63
|
|
|
185
|
-
function createSchemaOnlyAdapter({
|
|
186
|
-
code,
|
|
187
|
-
name,
|
|
188
|
-
provider,
|
|
189
|
-
path,
|
|
190
|
-
}: {
|
|
191
|
-
code: string;
|
|
192
|
-
name: string;
|
|
193
|
-
provider: ORMProvider;
|
|
194
|
-
path: string;
|
|
195
|
-
}): DatabasePlugin {
|
|
196
|
-
return {
|
|
197
|
-
...createInMemoryDatabasePlugin(),
|
|
198
|
-
adapterName: name,
|
|
199
|
-
provider,
|
|
200
|
-
generateSchema: (_version, schemaName = name) => ({
|
|
201
|
-
code,
|
|
202
|
-
path: path || schemaName,
|
|
203
|
-
}),
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const transactionBundle: Bundle = {
|
|
208
|
-
archiveByteSize: 1_024,
|
|
209
|
-
id: "00000000-0000-0000-0000-000000000777",
|
|
210
|
-
platform: "ios",
|
|
211
|
-
fileHash: "transaction-hash",
|
|
212
|
-
gitCommitHash: null,
|
|
213
|
-
storageUri: "s3://test-bucket/transaction.zip",
|
|
214
|
-
};
|
|
215
|
-
const transactionChannelId = "00000000-0000-0000-0000-000000000700";
|
|
216
|
-
|
|
217
64
|
describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
218
65
|
const db = new PGlite();
|
|
219
66
|
|
|
@@ -239,51 +86,8 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
239
86
|
createTestStoragePlugin("gs", readStoredText),
|
|
240
87
|
],
|
|
241
88
|
});
|
|
242
|
-
const prismaSchemaHotUpdater = createHotUpdater({
|
|
243
|
-
database: createSchemaOnlyAdapter({
|
|
244
|
-
code: RAW_PRISMA_SCHEMA,
|
|
245
|
-
name: "prisma",
|
|
246
|
-
path: "schema.prisma",
|
|
247
|
-
provider: "postgresql",
|
|
248
|
-
}),
|
|
249
|
-
});
|
|
250
|
-
const sqlitePrismaSchemaHotUpdater = createHotUpdater({
|
|
251
|
-
database: createSchemaOnlyAdapter({
|
|
252
|
-
code: RAW_PRISMA_SCHEMA,
|
|
253
|
-
name: "prisma",
|
|
254
|
-
path: "schema.prisma",
|
|
255
|
-
provider: "sqlite",
|
|
256
|
-
}),
|
|
257
|
-
});
|
|
258
|
-
const drizzleSchemaHotUpdater = createHotUpdater({
|
|
259
|
-
database: createSchemaOnlyAdapter({
|
|
260
|
-
code: RAW_DRIZZLE_SCHEMA,
|
|
261
|
-
name: "drizzle",
|
|
262
|
-
path: "hot-updater-schema.ts",
|
|
263
|
-
provider: "postgresql",
|
|
264
|
-
}),
|
|
265
|
-
});
|
|
266
|
-
|
|
267
89
|
it("uses the default generated schema artifact path for Drizzle", () => {
|
|
268
|
-
const adapter = drizzleAdapter({
|
|
269
|
-
db: {
|
|
270
|
-
_: {
|
|
271
|
-
fullSchema: {
|
|
272
|
-
bundle_patches: {},
|
|
273
|
-
bundles: {},
|
|
274
|
-
},
|
|
275
|
-
},
|
|
276
|
-
$count: vi.fn(),
|
|
277
|
-
delete: vi.fn(),
|
|
278
|
-
insert: vi.fn(),
|
|
279
|
-
query: {
|
|
280
|
-
bundle_patches: { findFirst: vi.fn(), findMany: vi.fn() },
|
|
281
|
-
bundles: { findFirst: vi.fn(), findMany: vi.fn() },
|
|
282
|
-
},
|
|
283
|
-
update: vi.fn(),
|
|
284
|
-
},
|
|
285
|
-
provider: "sqlite",
|
|
286
|
-
});
|
|
90
|
+
const adapter = drizzleAdapter({ db: {}, provider: "sqlite" });
|
|
287
91
|
|
|
288
92
|
expect(adapter.generateSchema?.("latest").path).toBe(
|
|
289
93
|
"hot-updater-schema.ts",
|
|
@@ -301,145 +105,71 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
301
105
|
|
|
302
106
|
beforeEach(async () => {
|
|
303
107
|
storageTexts.clear();
|
|
304
|
-
|
|
305
|
-
await db.
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
await db.exec(
|
|
108
|
+
// Every table but the settings rows, aggregates included.
|
|
109
|
+
const { rows } = await db.query<{ tablename: string }>(
|
|
110
|
+
"SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND tablename <> 'private_hot_updater_settings'",
|
|
111
|
+
);
|
|
112
|
+
await db.exec(
|
|
113
|
+
`TRUNCATE ${rows.map(({ tablename }) => `"${tablename}"`).join(", ")}`,
|
|
114
|
+
);
|
|
309
115
|
});
|
|
310
116
|
|
|
117
|
+
/** Stores a bundle with a disabled release, one deploy each. */
|
|
118
|
+
const deployBundle = (bundle: Bundle) =>
|
|
119
|
+
hotUpdater.core.deploy([
|
|
120
|
+
{
|
|
121
|
+
bundle,
|
|
122
|
+
release: {
|
|
123
|
+
channel: "production",
|
|
124
|
+
enabled: false,
|
|
125
|
+
fingerprintHash: null,
|
|
126
|
+
message: null,
|
|
127
|
+
shouldForceUpdate: false,
|
|
128
|
+
targetAppVersion: "*",
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
]);
|
|
132
|
+
|
|
311
133
|
afterAll(async () => {
|
|
312
134
|
await kysely.destroy();
|
|
313
135
|
await db.close();
|
|
314
136
|
});
|
|
315
137
|
|
|
316
138
|
describe("schema generation", () => {
|
|
317
|
-
it("
|
|
318
|
-
const
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
expect(code).
|
|
325
|
-
expect(code).toContain(
|
|
326
|
-
expect(code).toContain("
|
|
327
|
-
expect(code).toContain(
|
|
328
|
-
'channelRecord channels @relation("releases_channels", fields: [channel_id], references: [id], onUpdate: Restrict, onDelete: Restrict)',
|
|
329
|
-
);
|
|
330
|
-
expect(code).toContain(
|
|
331
|
-
'patches bundle_patches[] @relation("bundle_patches_bundles_patches")',
|
|
332
|
-
);
|
|
333
|
-
expect(code).toContain(
|
|
334
|
-
'baseForPatches bundle_patches[] @relation("bundle_patches_bundles_baseForPatches")',
|
|
335
|
-
);
|
|
336
|
-
expect(code).toContain(
|
|
337
|
-
'bundle bundles @relation("bundle_patches_bundles_patches"',
|
|
338
|
-
);
|
|
339
|
-
expect(code).toContain(
|
|
340
|
-
'baseBundle bundles @relation("bundle_patches_bundles_baseForPatches"',
|
|
341
|
-
);
|
|
342
|
-
expect(code).not.toContain(
|
|
343
|
-
'@@index([channel], map: "bundles_channel_idx")',
|
|
344
|
-
);
|
|
345
|
-
expect(code).toContain(
|
|
346
|
-
'@@index([scope_key, id], map: "releases_scope_order_idx")',
|
|
347
|
-
);
|
|
348
|
-
expect(code).toContain("scope_key String @db.VarChar(2048) @id");
|
|
349
|
-
expect(code).not.toContain("bundles_platform_idx");
|
|
350
|
-
expect(code).toContain(
|
|
351
|
-
'@@index([bundle_id], map: "bundle_patches_bundle_id_idx")',
|
|
352
|
-
);
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
it("omits the metadata JSON default for SQLite Prisma output", () => {
|
|
356
|
-
const code = generateSchema(sqlitePrismaSchemaHotUpdater, "latest").code;
|
|
357
|
-
|
|
358
|
-
expect(code).toContain("metadata Json");
|
|
359
|
-
expect(code).not.toContain('metadata Json @default("{}")');
|
|
139
|
+
it("passes the Prisma adapter's engine models through unchanged", () => {
|
|
140
|
+
const database = prismaAdapter({ prisma: {}, provider: "postgresql" });
|
|
141
|
+
const code = generateSchema(
|
|
142
|
+
createHotUpdater({ database }),
|
|
143
|
+
"latest",
|
|
144
|
+
).code;
|
|
145
|
+
|
|
146
|
+
expect(code).toBe(database.generateSchema?.("latest").code);
|
|
147
|
+
expect(code).toContain("model bundle_totals {");
|
|
148
|
+
expect(code).toContain("model private_hot_updater_settings {");
|
|
360
149
|
});
|
|
361
150
|
|
|
362
151
|
it("rejects generating a retired schema snapshot", () => {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
152
|
+
const database = prismaAdapter({ prisma: {}, provider: "postgresql" });
|
|
153
|
+
expect(() =>
|
|
154
|
+
generateSchema(createHotUpdater({ database }), "0.21.0"),
|
|
155
|
+
).toThrow("Invalid version 0.21.0");
|
|
366
156
|
});
|
|
367
157
|
|
|
368
|
-
it("
|
|
369
|
-
const
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
/export const bundle_patches = [\s\S]*?(?=\n\nexport const bundle_patchesRelations = )/,
|
|
375
|
-
)?.[0];
|
|
158
|
+
it("passes the Drizzle adapter's engine schema through unchanged", () => {
|
|
159
|
+
const database = drizzleAdapter({ db: {}, provider: "postgresql" });
|
|
160
|
+
const code = generateSchema(
|
|
161
|
+
createHotUpdater({ database }),
|
|
162
|
+
"latest",
|
|
163
|
+
).code;
|
|
376
164
|
|
|
377
|
-
expect(code).
|
|
378
|
-
|
|
379
|
-
);
|
|
380
|
-
expect(code).toContain('name: "bundle_patches_bundle_id_fk"');
|
|
381
|
-
expect(code).toContain('name: "bundle_patches_base_bundle_id_fk"');
|
|
382
|
-
expect(code).toContain('.onDelete("cascade")');
|
|
383
|
-
expect(bundlesBlock).not.toContain("bundles_channel_idx");
|
|
384
|
-
expect(bundlesBlock).not.toContain("bundles_platform_idx");
|
|
385
|
-
expect(bundlesBlock).not.toContain("target_app_version");
|
|
386
|
-
expect(bundlesBlock).not.toContain(
|
|
387
|
-
'index("bundle_patches_bundle_id_idx").on(table.bundle_id)',
|
|
388
|
-
);
|
|
389
|
-
expect(bundlePatchesBlock).toContain(
|
|
390
|
-
'index("bundle_patches_bundle_id_idx").on(table.bundle_id)',
|
|
391
|
-
);
|
|
392
|
-
expect(code).toContain(
|
|
393
|
-
'index("releases_scope_order_idx").on(table.scope_key, table.id)',
|
|
394
|
-
);
|
|
395
|
-
expect(code).toContain(
|
|
396
|
-
'scope_key: varchar("scope_key", { length: 2048 }).primaryKey().notNull()',
|
|
397
|
-
);
|
|
398
|
-
const generatedCode = generateDrizzleSchema("postgresql");
|
|
399
|
-
expect(generatedCode).toContain(
|
|
400
|
-
'id: varchar("id", { length: 255 }).primaryKey().notNull()',
|
|
401
|
-
);
|
|
402
|
-
expect(generatedCode).toContain(
|
|
403
|
-
'version: varchar("version", { length: 255 }).notNull().default("1.0.0")',
|
|
404
|
-
);
|
|
405
|
-
expect(generatedCode).toContain(
|
|
406
|
-
'uniqueIndex("channels_name_key").on(table.name)',
|
|
407
|
-
);
|
|
408
|
-
expect(generatedCode).toContain('name: "releases_channel_id_fk"');
|
|
409
|
-
expect(generatedCode).toContain(
|
|
410
|
-
'index("releases_channel_platform_order_idx").on(table.channel_id, table.platform, table.id)',
|
|
411
|
-
);
|
|
412
|
-
expect(generatedCode).not.toContain('key: varchar("key"');
|
|
413
|
-
expect(generatedCode).not.toContain('value: text("value"');
|
|
165
|
+
expect(code).toBe(database.generateSchema?.("latest").code);
|
|
166
|
+
expect(code).toContain('pgTable("bundle_totals"');
|
|
167
|
+
expect(code).toContain('pgTable("private_hot_updater_settings"');
|
|
414
168
|
});
|
|
415
169
|
});
|
|
416
170
|
|
|
417
171
|
describe("migrator enhancements", () => {
|
|
418
|
-
it("
|
|
419
|
-
expect(hotUpdaterSchemaVersions.map((schema) => schema.version)).toEqual([
|
|
420
|
-
"1.0.0",
|
|
421
|
-
]);
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
it("omits MySQL defaults for text and JSON columns", () => {
|
|
425
|
-
const sql = createTableSql("mysql").join("\n");
|
|
426
|
-
|
|
427
|
-
expect(sql).toContain("create table channels");
|
|
428
|
-
expect(sql).toContain("metadata json not null");
|
|
429
|
-
expect(sql).not.toContain("metadata json not null default");
|
|
430
|
-
expect(sql).toContain("`key` varchar(255) primary key");
|
|
431
|
-
expect(sql).not.toContain("\nkey varchar(255) primary key");
|
|
432
|
-
expect(sql).toContain(
|
|
433
|
-
"create table api_keys (\nid varchar(255) primary key not null",
|
|
434
|
-
);
|
|
435
|
-
expect(sql).not.toContain("create table api_keys (\nid text primary key");
|
|
436
|
-
expect(sql).toContain(
|
|
437
|
-
"create index bundle_patches_bundle_id_idx on bundle_patches(bundle_id)",
|
|
438
|
-
);
|
|
439
|
-
expect(sql).not.toContain("bundle_id(255)");
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
it("adds custom indexes and constraints to generated SQL", async () => {
|
|
172
|
+
it("generates the engine's tables, indexes, and settings rows, without foreign keys", async () => {
|
|
443
173
|
const migrationDb = new PGlite();
|
|
444
174
|
const migrationKysely = new Kysely<object>({
|
|
445
175
|
dialect: new PGliteDialect(migrationDb),
|
|
@@ -460,24 +190,15 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
460
190
|
const sql = result.getSQL?.() ?? "";
|
|
461
191
|
|
|
462
192
|
expect(sql).toContain(
|
|
463
|
-
|
|
464
|
-
);
|
|
465
|
-
expect(sql).toContain(
|
|
466
|
-
"add constraint releases_strategy_target_check check",
|
|
193
|
+
'CREATE INDEX IF NOT EXISTS "releases_byScope" ON "releases" ("scope_key", "id")',
|
|
467
194
|
);
|
|
195
|
+
expect(sql).not.toContain("FOREIGN KEY");
|
|
468
196
|
expect(sql).toContain(
|
|
469
|
-
|
|
197
|
+
`INSERT INTO "private_hot_updater_settings" ("key", "value", "_v") VALUES ('schema.engine', '1', 0)`,
|
|
470
198
|
);
|
|
471
|
-
|
|
472
|
-
"create index bundle_patches_bundle_id_idx on bundle_patches",
|
|
473
|
-
);
|
|
474
|
-
expect(sql).toContain("insert into private_hot_updater_settings");
|
|
199
|
+
// `updateSettings: false` leaves the settings step out of the plan only
|
|
475
200
|
expect(result.operations).not.toContainEqual(
|
|
476
|
-
expect.objectContaining({
|
|
477
|
-
sql: expect.stringContaining(
|
|
478
|
-
"insert into private_hot_updater_settings",
|
|
479
|
-
),
|
|
480
|
-
}),
|
|
201
|
+
expect.objectContaining({ type: "custom" }),
|
|
481
202
|
);
|
|
482
203
|
} finally {
|
|
483
204
|
await migrationKysely.destroy();
|
|
@@ -520,121 +241,6 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
520
241
|
}
|
|
521
242
|
});
|
|
522
243
|
|
|
523
|
-
it("honors soft relation mode by omitting SQL foreign keys", async () => {
|
|
524
|
-
const migrationDb = new PGlite();
|
|
525
|
-
const migrationKysely = new Kysely<object>({
|
|
526
|
-
dialect: new PGliteDialect(migrationDb),
|
|
527
|
-
});
|
|
528
|
-
const migrationHotUpdater = createHotUpdater({
|
|
529
|
-
database: kyselyAdapter({
|
|
530
|
-
db: migrationKysely,
|
|
531
|
-
provider: "postgresql",
|
|
532
|
-
relationMode: "fumadb",
|
|
533
|
-
}),
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
try {
|
|
537
|
-
const migrator = createMigrator(migrationHotUpdater);
|
|
538
|
-
const result = await migrator.migrateToLatest({
|
|
539
|
-
mode: "from-schema",
|
|
540
|
-
updateSettings: false,
|
|
541
|
-
});
|
|
542
|
-
const sql = result.getSQL?.() ?? "";
|
|
543
|
-
|
|
544
|
-
expect(sql).not.toContain("add constraint bundle_patches_bundle_id_fk");
|
|
545
|
-
expect(result.operations).not.toContainEqual(
|
|
546
|
-
expect.objectContaining({
|
|
547
|
-
sql: expect.stringContaining("bundle_patches_bundle_id_fk"),
|
|
548
|
-
}),
|
|
549
|
-
);
|
|
550
|
-
} finally {
|
|
551
|
-
await migrationKysely.destroy();
|
|
552
|
-
await migrationDb.close();
|
|
553
|
-
}
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
it("omits unsupported SQLite alter constraint statements", async () => {
|
|
557
|
-
const migrationDb = new PGlite();
|
|
558
|
-
const migrationKysely = new Kysely<object>({
|
|
559
|
-
dialect: new PGliteDialect(migrationDb),
|
|
560
|
-
});
|
|
561
|
-
const migrationHotUpdater = createHotUpdater({
|
|
562
|
-
database: kyselyAdapter({
|
|
563
|
-
db: migrationKysely,
|
|
564
|
-
provider: "sqlite",
|
|
565
|
-
}),
|
|
566
|
-
});
|
|
567
|
-
|
|
568
|
-
try {
|
|
569
|
-
const migrator = createMigrator(migrationHotUpdater);
|
|
570
|
-
const result = await migrator.migrateToLatest({
|
|
571
|
-
mode: "from-schema",
|
|
572
|
-
updateSettings: false,
|
|
573
|
-
});
|
|
574
|
-
const sql = result.getSQL?.() ?? "";
|
|
575
|
-
|
|
576
|
-
expect(sql).not.toContain("alter table bundles add constraint");
|
|
577
|
-
expect(sql).not.toContain("alter table bundle_patches add constraint");
|
|
578
|
-
expect(result.operations).not.toContainEqual(
|
|
579
|
-
expect.objectContaining({
|
|
580
|
-
sql: expect.stringContaining("add constraint"),
|
|
581
|
-
}),
|
|
582
|
-
);
|
|
583
|
-
} finally {
|
|
584
|
-
await migrationKysely.destroy();
|
|
585
|
-
await migrationDb.close();
|
|
586
|
-
}
|
|
587
|
-
});
|
|
588
|
-
|
|
589
|
-
it("creates MongoDB indexes for runtime query fields", async () => {
|
|
590
|
-
const collection = {
|
|
591
|
-
find: vi.fn(() => ({
|
|
592
|
-
limit: () => ({ toArray: async () => [] }),
|
|
593
|
-
})),
|
|
594
|
-
listIndexes: () => ({ toArray: async () => [] }),
|
|
595
|
-
};
|
|
596
|
-
const client = {
|
|
597
|
-
db: () => ({
|
|
598
|
-
collection: () => collection,
|
|
599
|
-
}),
|
|
600
|
-
} as unknown as MongoClient;
|
|
601
|
-
const mongoHotUpdater = createHotUpdater({
|
|
602
|
-
database: mongoAdapter({ client }),
|
|
603
|
-
});
|
|
604
|
-
const result = await createMigrator(mongoHotUpdater).migrateToLatest({
|
|
605
|
-
mode: "from-schema",
|
|
606
|
-
});
|
|
607
|
-
|
|
608
|
-
expect(result.operations).toEqual(
|
|
609
|
-
expect.arrayContaining([
|
|
610
|
-
expect.objectContaining({
|
|
611
|
-
description:
|
|
612
|
-
"Create unique MongoDB index: bundles_id_idx on bundles(id)",
|
|
613
|
-
}),
|
|
614
|
-
expect.objectContaining({
|
|
615
|
-
description:
|
|
616
|
-
"Create unique MongoDB index: bundle_patches_id_idx on bundle_patches(id)",
|
|
617
|
-
}),
|
|
618
|
-
expect.objectContaining({
|
|
619
|
-
description:
|
|
620
|
-
"Create unique MongoDB index: release_catalogs_scope_key_idx on release_catalogs(scope_key)",
|
|
621
|
-
}),
|
|
622
|
-
expect.objectContaining({
|
|
623
|
-
description:
|
|
624
|
-
"Create MongoDB index: releases_fingerprint_hash_idx on releases(fingerprint_hash)",
|
|
625
|
-
}),
|
|
626
|
-
expect.objectContaining({
|
|
627
|
-
description:
|
|
628
|
-
"Create MongoDB index: bundles_platform_idx on bundles(platform)",
|
|
629
|
-
}),
|
|
630
|
-
expect.objectContaining({
|
|
631
|
-
description:
|
|
632
|
-
"Create MongoDB index: bundle_patches_base_bundle_id_idx on bundle_patches(base_bundle_id)",
|
|
633
|
-
}),
|
|
634
|
-
]),
|
|
635
|
-
);
|
|
636
|
-
});
|
|
637
|
-
|
|
638
244
|
it("rejects from-database migrations explicitly", async () => {
|
|
639
245
|
const migrationDb = new PGlite();
|
|
640
246
|
const migrationKysely = new Kysely<object>({
|
|
@@ -675,9 +281,9 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
675
281
|
|
|
676
282
|
try {
|
|
677
283
|
await expect(
|
|
678
|
-
migrationHotUpdater.
|
|
284
|
+
migrationHotUpdater.core.listBundles({ limit: 10 }),
|
|
679
285
|
).rejects.toThrow(
|
|
680
|
-
|
|
286
|
+
'Hot Updater schema setting "schema.engine" for kysely is missing',
|
|
681
287
|
);
|
|
682
288
|
} finally {
|
|
683
289
|
await migrationKysely.destroy();
|
|
@@ -707,338 +313,40 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
707
313
|
values ('version', '0.21.0');
|
|
708
314
|
`);
|
|
709
315
|
|
|
710
|
-
await expect(
|
|
711
|
-
|
|
712
|
-
);
|
|
316
|
+
await expect(
|
|
317
|
+
migrationHotUpdater.core.listChannels(),
|
|
318
|
+
).rejects.toBeInstanceOf(HotUpdaterSchemaMigrationRequiredError);
|
|
713
319
|
} finally {
|
|
714
320
|
await migrationKysely.destroy();
|
|
715
321
|
await migrationDb.close();
|
|
716
322
|
}
|
|
717
323
|
});
|
|
718
|
-
|
|
719
|
-
it("rejects runtime access when a MongoDB schema is stale", async () => {
|
|
720
|
-
const settings = {
|
|
721
|
-
find: vi.fn(({ key }: { readonly key: string }) => ({
|
|
722
|
-
limit: () => ({
|
|
723
|
-
toArray: async () =>
|
|
724
|
-
key === "version" ? [{ key, value: "0.21.0" }] : [],
|
|
725
|
-
}),
|
|
726
|
-
})),
|
|
727
|
-
};
|
|
728
|
-
const bundles = {
|
|
729
|
-
countDocuments: vi.fn(async () => 0),
|
|
730
|
-
find: vi.fn(),
|
|
731
|
-
findOne: vi.fn(),
|
|
732
|
-
};
|
|
733
|
-
const patches = {
|
|
734
|
-
find: vi.fn(),
|
|
735
|
-
};
|
|
736
|
-
const client = {
|
|
737
|
-
db: () => ({
|
|
738
|
-
collection: (name: string) => {
|
|
739
|
-
if (name === "private_hot_updater_settings") return settings;
|
|
740
|
-
if (name === "bundle_patches") return patches;
|
|
741
|
-
return bundles;
|
|
742
|
-
},
|
|
743
|
-
}),
|
|
744
|
-
} as unknown as MongoClient;
|
|
745
|
-
const mongoHotUpdater = createHotUpdater({
|
|
746
|
-
database: mongoAdapter({ client }),
|
|
747
|
-
});
|
|
748
|
-
|
|
749
|
-
await expect(mongoHotUpdater.getBundles({ limit: 10 })).rejects.toThrow(
|
|
750
|
-
"Hot Updater v1 cannot migrate schema 0.21.0 in place.",
|
|
751
|
-
);
|
|
752
|
-
expect(bundles.countDocuments).not.toHaveBeenCalled();
|
|
753
|
-
});
|
|
754
|
-
});
|
|
755
|
-
|
|
756
|
-
describe("adapter filters", () => {
|
|
757
|
-
it("returns an empty Kysely page for empty set filters", async () => {
|
|
758
|
-
const byId = await hotUpdater.getBundles({
|
|
759
|
-
limit: 10,
|
|
760
|
-
where: { id: { in: [] } },
|
|
761
|
-
});
|
|
762
|
-
expect(byId.data).toEqual([]);
|
|
763
|
-
expect(byId.pagination.total).toBe(0);
|
|
764
|
-
});
|
|
765
|
-
|
|
766
|
-
it("commits Prisma bundle changes inside a transaction when available", async () => {
|
|
767
|
-
const rootBundles = {
|
|
768
|
-
count: vi.fn(),
|
|
769
|
-
create: vi.fn(),
|
|
770
|
-
deleteMany: vi.fn(),
|
|
771
|
-
findFirst: vi.fn(),
|
|
772
|
-
findMany: vi.fn(),
|
|
773
|
-
update: vi.fn(),
|
|
774
|
-
upsert: vi.fn(),
|
|
775
|
-
};
|
|
776
|
-
const rootPatches = {
|
|
777
|
-
count: vi.fn(),
|
|
778
|
-
create: vi.fn(),
|
|
779
|
-
deleteMany: vi.fn(),
|
|
780
|
-
findFirst: vi.fn(),
|
|
781
|
-
findMany: vi.fn(),
|
|
782
|
-
update: vi.fn(),
|
|
783
|
-
upsert: vi.fn(),
|
|
784
|
-
};
|
|
785
|
-
const channels = {
|
|
786
|
-
count: vi.fn(),
|
|
787
|
-
create: vi.fn(),
|
|
788
|
-
deleteMany: vi.fn(),
|
|
789
|
-
findFirst: vi.fn(async () => ({
|
|
790
|
-
id: transactionChannelId,
|
|
791
|
-
name: "production",
|
|
792
|
-
})),
|
|
793
|
-
findMany: vi.fn(),
|
|
794
|
-
update: vi.fn(),
|
|
795
|
-
upsert: vi.fn(),
|
|
796
|
-
};
|
|
797
|
-
const txBundles = {
|
|
798
|
-
...rootBundles,
|
|
799
|
-
create: vi.fn(async ({ data }) => data),
|
|
800
|
-
};
|
|
801
|
-
const txPatches = { ...rootPatches };
|
|
802
|
-
const $transaction = vi.fn(
|
|
803
|
-
async (operation: (tx: Record<string, unknown>) => Promise<unknown>) =>
|
|
804
|
-
operation({
|
|
805
|
-
bundle_patches: txPatches,
|
|
806
|
-
bundles: txBundles,
|
|
807
|
-
channels,
|
|
808
|
-
}),
|
|
809
|
-
);
|
|
810
|
-
const adapter = prismaAdapter({
|
|
811
|
-
prisma: {
|
|
812
|
-
$transaction,
|
|
813
|
-
bundle_patches: rootPatches,
|
|
814
|
-
bundles: rootBundles,
|
|
815
|
-
channels,
|
|
816
|
-
},
|
|
817
|
-
provider: "postgresql",
|
|
818
|
-
});
|
|
819
|
-
|
|
820
|
-
await adapter.commit({
|
|
821
|
-
changes: [
|
|
822
|
-
{
|
|
823
|
-
model: "bundles",
|
|
824
|
-
operation: "insert",
|
|
825
|
-
row: bundleToRow(transactionBundle),
|
|
826
|
-
},
|
|
827
|
-
],
|
|
828
|
-
});
|
|
829
|
-
|
|
830
|
-
expect($transaction).toHaveBeenCalledTimes(1);
|
|
831
|
-
expect(txBundles.create).toHaveBeenCalledTimes(1);
|
|
832
|
-
expect(rootBundles.create).not.toHaveBeenCalled();
|
|
833
|
-
});
|
|
834
|
-
|
|
835
|
-
it("commits Drizzle bundle changes inside a transaction when available", async () => {
|
|
836
|
-
const tables = {
|
|
837
|
-
bundle_events: {
|
|
838
|
-
id: "event_id",
|
|
839
|
-
},
|
|
840
|
-
bundle_patches: {
|
|
841
|
-
bundle_id: "bundle_id",
|
|
842
|
-
id: "patch_id",
|
|
843
|
-
order_index: "order_index",
|
|
844
|
-
},
|
|
845
|
-
bundles: {
|
|
846
|
-
id: "id",
|
|
847
|
-
},
|
|
848
|
-
channels: {
|
|
849
|
-
id: sql.raw("channel_id"),
|
|
850
|
-
name: sql.raw("channel_name"),
|
|
851
|
-
},
|
|
852
|
-
api_keys: {
|
|
853
|
-
id: "access_key_id",
|
|
854
|
-
},
|
|
855
|
-
release_catalogs: {
|
|
856
|
-
scope_key: "scope_key",
|
|
857
|
-
},
|
|
858
|
-
releases: {
|
|
859
|
-
id: "release_id",
|
|
860
|
-
scope_key: "scope_key",
|
|
861
|
-
},
|
|
862
|
-
};
|
|
863
|
-
const rootInsert = vi.fn(() => ({
|
|
864
|
-
values: vi.fn(() => ({ execute: vi.fn(async () => undefined) })),
|
|
865
|
-
}));
|
|
866
|
-
const txInsert = vi.fn(() => ({
|
|
867
|
-
values: vi.fn(() => ({ execute: vi.fn(async () => undefined) })),
|
|
868
|
-
}));
|
|
869
|
-
const createDb = (insert: typeof rootInsert) => ({
|
|
870
|
-
_: { fullSchema: tables },
|
|
871
|
-
$count: vi.fn(),
|
|
872
|
-
delete: vi.fn(() => ({
|
|
873
|
-
where: vi.fn(async () => undefined),
|
|
874
|
-
})),
|
|
875
|
-
insert,
|
|
876
|
-
query: {
|
|
877
|
-
bundle_events: {
|
|
878
|
-
findFirst: vi.fn(),
|
|
879
|
-
findMany: vi.fn(),
|
|
880
|
-
},
|
|
881
|
-
bundle_patches: {
|
|
882
|
-
findFirst: vi.fn(),
|
|
883
|
-
findMany: vi.fn(),
|
|
884
|
-
},
|
|
885
|
-
bundles: {
|
|
886
|
-
findFirst: vi.fn(async () => undefined),
|
|
887
|
-
findMany: vi.fn(),
|
|
888
|
-
},
|
|
889
|
-
channels: {
|
|
890
|
-
findFirst: vi.fn(async () => ({
|
|
891
|
-
id: transactionChannelId,
|
|
892
|
-
name: "production",
|
|
893
|
-
})),
|
|
894
|
-
findMany: vi.fn(),
|
|
895
|
-
},
|
|
896
|
-
api_keys: {
|
|
897
|
-
findFirst: vi.fn(),
|
|
898
|
-
findMany: vi.fn(),
|
|
899
|
-
},
|
|
900
|
-
release_catalogs: {
|
|
901
|
-
findFirst: vi.fn(),
|
|
902
|
-
findMany: vi.fn(),
|
|
903
|
-
},
|
|
904
|
-
releases: {
|
|
905
|
-
findFirst: vi.fn(),
|
|
906
|
-
findMany: vi.fn(),
|
|
907
|
-
},
|
|
908
|
-
},
|
|
909
|
-
select: vi.fn(),
|
|
910
|
-
update: vi.fn(() => ({
|
|
911
|
-
set: vi.fn(() => ({
|
|
912
|
-
where: vi.fn(async () => undefined),
|
|
913
|
-
})),
|
|
914
|
-
})),
|
|
915
|
-
});
|
|
916
|
-
const txDb = createDb(txInsert);
|
|
917
|
-
const transaction = vi.fn(
|
|
918
|
-
async (operation: (tx: typeof txDb) => Promise<unknown>) =>
|
|
919
|
-
operation(txDb),
|
|
920
|
-
);
|
|
921
|
-
const db = {
|
|
922
|
-
...createDb(rootInsert),
|
|
923
|
-
transaction,
|
|
924
|
-
};
|
|
925
|
-
const adapter = drizzleAdapter({
|
|
926
|
-
db,
|
|
927
|
-
provider: "postgresql",
|
|
928
|
-
});
|
|
929
|
-
|
|
930
|
-
await adapter.commit({
|
|
931
|
-
changes: [
|
|
932
|
-
{
|
|
933
|
-
model: "bundles",
|
|
934
|
-
operation: "insert",
|
|
935
|
-
row: bundleToRow(transactionBundle),
|
|
936
|
-
},
|
|
937
|
-
],
|
|
938
|
-
});
|
|
939
|
-
|
|
940
|
-
expect(transaction).toHaveBeenCalledTimes(1);
|
|
941
|
-
expect(txInsert).toHaveBeenCalledTimes(1);
|
|
942
|
-
expect(rootInsert).not.toHaveBeenCalled();
|
|
943
|
-
});
|
|
944
|
-
|
|
945
|
-
it("does not expose an implicit MongoDB transaction", () => {
|
|
946
|
-
const bundles = {
|
|
947
|
-
countDocuments: vi.fn(),
|
|
948
|
-
deleteMany: vi.fn(),
|
|
949
|
-
distinct: vi.fn(),
|
|
950
|
-
find: vi.fn(),
|
|
951
|
-
findOne: vi.fn(),
|
|
952
|
-
updateOne: vi.fn(async () => undefined),
|
|
953
|
-
};
|
|
954
|
-
const patches = {
|
|
955
|
-
deleteMany: vi.fn(async () => undefined),
|
|
956
|
-
find: vi.fn(),
|
|
957
|
-
insertMany: vi.fn(),
|
|
958
|
-
};
|
|
959
|
-
const client = {
|
|
960
|
-
db: () => ({
|
|
961
|
-
collection: (name: string) =>
|
|
962
|
-
name === "bundle_patches" ? patches : bundles,
|
|
963
|
-
}),
|
|
964
|
-
} as unknown as MongoClient;
|
|
965
|
-
const adapter = mongoAdapter({ client });
|
|
966
|
-
|
|
967
|
-
expect(Reflect.has(adapter, "transaction")).toBe(false);
|
|
968
|
-
});
|
|
969
|
-
|
|
970
|
-
it("uses a MongoDB session when transactions are enabled", async () => {
|
|
971
|
-
const client = new MongoClient("mongodb://localhost");
|
|
972
|
-
const session = client.startSession();
|
|
973
|
-
const withTransaction = vi.fn(
|
|
974
|
-
async (operation: (session: ClientSession) => Promise<unknown>) =>
|
|
975
|
-
operation(session),
|
|
976
|
-
);
|
|
977
|
-
Object.defineProperty(session, "withTransaction", {
|
|
978
|
-
value: withTransaction,
|
|
979
|
-
});
|
|
980
|
-
const insertOne = vi.fn(async () => undefined);
|
|
981
|
-
Object.defineProperty(client, "db", {
|
|
982
|
-
value: () => ({
|
|
983
|
-
collection: () => ({
|
|
984
|
-
findOne: vi.fn(async () => ({
|
|
985
|
-
id: transactionChannelId,
|
|
986
|
-
name: "production",
|
|
987
|
-
})),
|
|
988
|
-
insertOne,
|
|
989
|
-
updateOne: vi.fn(async () => ({ matchedCount: 1 })),
|
|
990
|
-
}),
|
|
991
|
-
}),
|
|
992
|
-
});
|
|
993
|
-
const withSession = vi.fn(
|
|
994
|
-
async (operation: (session: ClientSession) => Promise<unknown>) =>
|
|
995
|
-
operation(session),
|
|
996
|
-
);
|
|
997
|
-
Object.defineProperty(client, "withSession", { value: withSession });
|
|
998
|
-
const adapter = mongoAdapter({ client, transactions: true });
|
|
999
|
-
|
|
1000
|
-
await adapter.commit({
|
|
1001
|
-
changes: [
|
|
1002
|
-
{
|
|
1003
|
-
model: "bundles",
|
|
1004
|
-
operation: "insert",
|
|
1005
|
-
row: bundleToRow(transactionBundle),
|
|
1006
|
-
},
|
|
1007
|
-
],
|
|
1008
|
-
});
|
|
1009
|
-
|
|
1010
|
-
expect(withSession).toHaveBeenCalledTimes(1);
|
|
1011
|
-
expect(withTransaction).toHaveBeenCalledTimes(1);
|
|
1012
|
-
expect(insertOne).toHaveBeenCalledWith(bundleToRow(transactionBundle), {
|
|
1013
|
-
session,
|
|
1014
|
-
});
|
|
1015
|
-
});
|
|
1016
324
|
});
|
|
1017
325
|
|
|
1018
|
-
describe("
|
|
326
|
+
describe("getBundle", () => {
|
|
1019
327
|
it("should retrieve bundle by id without Prisma validation errors", async () => {
|
|
1020
328
|
const bundle: Bundle = {
|
|
1021
|
-
archiveByteSize: 1_024,
|
|
1022
329
|
id: "00000000-0000-0000-0000-000000000010",
|
|
1023
330
|
platform: "ios",
|
|
1024
|
-
fileHash: "test-hash",
|
|
1025
331
|
gitCommitHash: null,
|
|
1026
|
-
|
|
332
|
+
manifestStorageUri: "s3://test-bucket/test/manifest.json",
|
|
333
|
+
manifestFileHash: "test-manifest-hash",
|
|
334
|
+
assetBaseStorageUri: "s3://test-bucket/assets",
|
|
1027
335
|
};
|
|
1028
336
|
|
|
1029
|
-
await
|
|
337
|
+
await deployBundle(bundle);
|
|
1030
338
|
|
|
1031
|
-
|
|
1032
|
-
const retrieved = await hotUpdater.getBundleById(bundle.id);
|
|
339
|
+
const retrieved = await hotUpdater.core.getBundle(bundle.id);
|
|
1033
340
|
|
|
1034
|
-
expect(retrieved).
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
341
|
+
expect(retrieved?.bundle).toMatchObject({
|
|
342
|
+
id: bundle.id,
|
|
343
|
+
platform: bundle.platform,
|
|
344
|
+
manifest_file_hash: bundle.manifestFileHash,
|
|
345
|
+
});
|
|
1038
346
|
});
|
|
1039
347
|
|
|
1040
348
|
it("should return null for non-existent bundle id", async () => {
|
|
1041
|
-
const retrieved = await hotUpdater.
|
|
349
|
+
const retrieved = await hotUpdater.core.getBundle(
|
|
1042
350
|
"99999999-9999-9999-9999-999999999999",
|
|
1043
351
|
);
|
|
1044
352
|
|
|
@@ -1046,18 +354,12 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
1046
354
|
});
|
|
1047
355
|
});
|
|
1048
356
|
|
|
1049
|
-
describe("
|
|
1050
|
-
it("
|
|
1051
|
-
await hotUpdater.
|
|
1052
|
-
|
|
1053
|
-
row: { id: "channel-production", name: "production" },
|
|
1054
|
-
});
|
|
1055
|
-
await hotUpdater.insertChannel({
|
|
1056
|
-
onConflict: "returnExisting",
|
|
1057
|
-
row: { id: "channel-staging", name: "staging" },
|
|
1058
|
-
});
|
|
357
|
+
describe("listChannels", () => {
|
|
358
|
+
it("lists channel rows by name", async () => {
|
|
359
|
+
await hotUpdater.core.ensureChannel("staging");
|
|
360
|
+
await hotUpdater.core.ensureChannel("production");
|
|
1059
361
|
|
|
1060
|
-
const channels = await hotUpdater.
|
|
362
|
+
const channels = await hotUpdater.core.listChannels();
|
|
1061
363
|
|
|
1062
364
|
expect(channels).toHaveLength(2);
|
|
1063
365
|
expect(channels.map(({ name }) => name)).toEqual([
|
|
@@ -1066,8 +368,8 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
1066
368
|
]);
|
|
1067
369
|
});
|
|
1068
370
|
|
|
1069
|
-
it("should return empty array when no
|
|
1070
|
-
const channels = await hotUpdater.
|
|
371
|
+
it("should return empty array when no channels exist", async () => {
|
|
372
|
+
const channels = await hotUpdater.core.listChannels();
|
|
1071
373
|
expect(channels).toEqual([]);
|
|
1072
374
|
});
|
|
1073
375
|
});
|
|
@@ -1083,23 +385,34 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
1083
385
|
vi.useRealTimers();
|
|
1084
386
|
});
|
|
1085
387
|
|
|
1086
|
-
it("resolves
|
|
388
|
+
it("resolves manifest and asset URIs via s3StoragePlugin", async () => {
|
|
1087
389
|
const bundle: Bundle = {
|
|
1088
|
-
archiveByteSize: 1_024,
|
|
1089
390
|
id: "00000000-0000-0000-0000-000000000001",
|
|
1090
391
|
platform: "ios",
|
|
1091
|
-
fileHash: "hash123",
|
|
1092
392
|
gitCommitHash: null,
|
|
1093
|
-
|
|
393
|
+
manifestStorageUri: "s3://test-bucket/bundles/bundle/manifest.json",
|
|
394
|
+
manifestFileHash: "manifest-hash",
|
|
395
|
+
assetBaseStorageUri: "s3://test-bucket/assets",
|
|
1094
396
|
};
|
|
397
|
+
storageTexts.set(
|
|
398
|
+
bundle.manifestStorageUri,
|
|
399
|
+
JSON.stringify({
|
|
400
|
+
bundleId: bundle.id,
|
|
401
|
+
assets: { "assets/logo.png": { fileHash: "logo-hash" } },
|
|
402
|
+
}),
|
|
403
|
+
);
|
|
1095
404
|
|
|
1096
|
-
await
|
|
405
|
+
await deployBundle(bundle);
|
|
1097
406
|
|
|
1098
|
-
const updateInfo = await hotUpdater.getArtifactInfo(
|
|
407
|
+
const updateInfo = await hotUpdater.core.getArtifactInfo(
|
|
408
|
+
bundle.id,
|
|
409
|
+
NIL_UUID,
|
|
410
|
+
1,
|
|
411
|
+
);
|
|
1099
412
|
|
|
1100
413
|
expect(updateInfo).not.toBeNull();
|
|
1101
|
-
expect(updateInfo?.
|
|
1102
|
-
"https://s3.example.com/test-bucket/bundles/bundle.
|
|
414
|
+
expect(updateInfo?.manifestUrl).toBe(
|
|
415
|
+
"https://s3.example.com/test-bucket/bundles/bundle/manifest.json",
|
|
1103
416
|
);
|
|
1104
417
|
});
|
|
1105
418
|
|
|
@@ -1109,34 +422,26 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
1109
422
|
const nextManifestStorageUri =
|
|
1110
423
|
"s3://test-bucket/releases/bundles/00000000-0000-0000-0000-000000000102/manifest.json";
|
|
1111
424
|
const olderBundle: Bundle = {
|
|
1112
|
-
archiveByteSize: 1_024,
|
|
1113
425
|
id: "00000000-0000-0000-0000-000000000100",
|
|
1114
426
|
platform: "ios",
|
|
1115
|
-
fileHash: "hash-older-zip",
|
|
1116
427
|
gitCommitHash: null,
|
|
1117
|
-
|
|
1118
|
-
|
|
428
|
+
assetBaseStorageUri: "s3://test-bucket/releases/assets",
|
|
429
|
+
manifestFileHash: "manifest-older",
|
|
430
|
+
manifestStorageUri:
|
|
431
|
+
"s3://test-bucket/releases/bundles/00000000-0000-0000-0000-000000000100/manifest.json",
|
|
1119
432
|
};
|
|
1120
433
|
const currentBundle: Bundle = {
|
|
1121
|
-
archiveByteSize: 1_024,
|
|
1122
434
|
id: "00000000-0000-0000-0000-000000000101",
|
|
1123
435
|
platform: "ios",
|
|
1124
|
-
fileHash: "hash-current-zip",
|
|
1125
436
|
gitCommitHash: null,
|
|
1126
|
-
storageUri:
|
|
1127
|
-
"s3://test-bucket/releases/bundles/00000000-0000-0000-0000-000000000101/bundle.zip",
|
|
1128
437
|
assetBaseStorageUri: "s3://test-bucket/releases/assets",
|
|
1129
438
|
manifestFileHash: "sig:manifest-current",
|
|
1130
439
|
manifestStorageUri: currentManifestStorageUri,
|
|
1131
440
|
};
|
|
1132
441
|
const nextBundle: Bundle = {
|
|
1133
|
-
archiveByteSize: 1_024,
|
|
1134
442
|
id: "00000000-0000-0000-0000-000000000102",
|
|
1135
443
|
platform: "ios",
|
|
1136
|
-
fileHash: "hash-next-zip",
|
|
1137
444
|
gitCommitHash: null,
|
|
1138
|
-
storageUri:
|
|
1139
|
-
"s3://test-bucket/releases/bundles/00000000-0000-0000-0000-000000000102/bundle.zip",
|
|
1140
445
|
assetBaseStorageUri: "s3://test-bucket/releases/assets",
|
|
1141
446
|
manifestFileHash: "sig:manifest-next",
|
|
1142
447
|
manifestStorageUri: nextManifestStorageUri,
|
|
@@ -1193,35 +498,26 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
1193
498
|
});
|
|
1194
499
|
});
|
|
1195
500
|
|
|
1196
|
-
await
|
|
1197
|
-
await
|
|
1198
|
-
await
|
|
501
|
+
await deployBundle(olderBundle);
|
|
502
|
+
await deployBundle(currentBundle);
|
|
503
|
+
await deployBundle(nextBundle);
|
|
1199
504
|
vi.stubGlobal("fetch", fetchMock);
|
|
1200
505
|
|
|
1201
506
|
try {
|
|
1202
507
|
await expect(
|
|
1203
|
-
hotUpdater.getArtifactInfo(nextBundle.id, currentBundle.id),
|
|
1204
|
-
).resolves.
|
|
1205
|
-
|
|
508
|
+
hotUpdater.core.getArtifactInfo(nextBundle.id, currentBundle.id, 1),
|
|
509
|
+
).resolves.toMatchObject({
|
|
510
|
+
artifactProtocolVersion: 1,
|
|
511
|
+
assets: {
|
|
512
|
+
"assets/logo.png": {
|
|
513
|
+
file: { url: expect.any(String) },
|
|
514
|
+
fileHash: "hash-logo",
|
|
515
|
+
},
|
|
1206
516
|
"index.ios.bundle": {
|
|
1207
|
-
file: {
|
|
1208
|
-
compression: "br",
|
|
1209
|
-
url: "https://s3.example.com/test-bucket/releases/assets/sha256/ha/hash-new-bundle.br",
|
|
1210
|
-
},
|
|
517
|
+
file: { url: expect.any(String) },
|
|
1211
518
|
fileHash: "hash-new-bundle",
|
|
1212
|
-
patch: {
|
|
1213
|
-
algorithm: "bsdiff",
|
|
1214
|
-
baseBundleId: currentBundle.id,
|
|
1215
|
-
baseFileHash: "hash-old-bundle",
|
|
1216
|
-
patchFileHash: "hash-bsdiff",
|
|
1217
|
-
patchUrl:
|
|
1218
|
-
"https://s3.example.com/test-bucket/releases/bundles/00000000-0000-0000-0000-000000000102/patches/00000000-0000-0000-0000-000000000101/index.ios.bundle.bsdiff",
|
|
1219
|
-
},
|
|
1220
519
|
},
|
|
1221
520
|
},
|
|
1222
|
-
fileHash: "hash-next-zip",
|
|
1223
|
-
fileUrl:
|
|
1224
|
-
"https://s3.example.com/test-bucket/releases/bundles/00000000-0000-0000-0000-000000000102/bundle.zip",
|
|
1225
521
|
manifestFileHash: "sig:manifest-next",
|
|
1226
522
|
manifestUrl:
|
|
1227
523
|
"https://s3.example.com/test-bucket/releases/bundles/00000000-0000-0000-0000-000000000102/manifest.json",
|
|
@@ -1236,26 +532,22 @@ describe("server/db hotUpdater (PGlite + Kysely)", async () => {
|
|
|
1236
532
|
const nextManifestStorageUri =
|
|
1237
533
|
"s3://test-bucket/releases/bundles/00000000-0000-0000-0000-000000000109/manifest.json";
|
|
1238
534
|
const nextBundle: Bundle = {
|
|
1239
|
-
archiveByteSize: 1_024,
|
|
1240
535
|
id: "00000000-0000-0000-0000-000000000109",
|
|
1241
536
|
platform: "ios",
|
|
1242
|
-
fileHash: "hash-next-zip",
|
|
1243
537
|
gitCommitHash: null,
|
|
1244
|
-
storageUri:
|
|
1245
|
-
"s3://test-bucket/releases/bundles/00000000-0000-0000-0000-000000000109/bundle.zip",
|
|
1246
538
|
assetBaseStorageUri: "s3://test-bucket/releases/assets",
|
|
1247
539
|
manifestFileHash: "sig:manifest-next",
|
|
1248
540
|
manifestStorageUri: nextManifestStorageUri,
|
|
1249
541
|
};
|
|
1250
542
|
|
|
1251
|
-
await
|
|
543
|
+
await deployBundle(nextBundle);
|
|
1252
544
|
storageTexts.set(
|
|
1253
545
|
nextManifestStorageUri,
|
|
1254
546
|
new Error("storage read failed"),
|
|
1255
547
|
);
|
|
1256
548
|
|
|
1257
549
|
await expect(
|
|
1258
|
-
hotUpdater.getArtifactInfo(nextBundle.id, NIL_UUID),
|
|
550
|
+
hotUpdater.core.getArtifactInfo(nextBundle.id, NIL_UUID, 1),
|
|
1259
551
|
).rejects.toThrow("storage read failed");
|
|
1260
552
|
});
|
|
1261
553
|
});
|