@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,175 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import type { DatabaseSync, SqliteValue } from "node:sqlite";
|
|
7
|
+
import { promisify } from "node:util";
|
|
8
|
+
|
|
9
|
+
import type { PGlite, Transaction } from "@electric-sql/pglite";
|
|
10
|
+
import type { Pool as MysqlPool, PoolConnection } from "mysql2/promise";
|
|
11
|
+
|
|
12
|
+
import { prismaAdapter, type PrismaProvider } from "./prisma";
|
|
13
|
+
import type {
|
|
14
|
+
PrismaRawClient,
|
|
15
|
+
PrismaTransactionalClient,
|
|
16
|
+
} from "./prismaExecutor";
|
|
17
|
+
|
|
18
|
+
/** A database error as Prisma reports a failed raw query: P2010, with the database's code. */
|
|
19
|
+
const prismaError = (error: unknown) => {
|
|
20
|
+
const { code, errcode, errno, message } = error as Record<string, unknown>;
|
|
21
|
+
const database = String(errcode ?? errno ?? code);
|
|
22
|
+
return Object.assign(
|
|
23
|
+
new Error(
|
|
24
|
+
`Raw query failed. Code: \`${database}\`. Message: \`${String(message)}\``,
|
|
25
|
+
),
|
|
26
|
+
{
|
|
27
|
+
name: "PrismaClientKnownRequestError",
|
|
28
|
+
code: "P2010",
|
|
29
|
+
meta: { code: database, message: String(message) },
|
|
30
|
+
},
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const raw = (
|
|
35
|
+
query: (sql: string, params: unknown[]) => Promise<unknown[]>,
|
|
36
|
+
execute: (sql: string, params: unknown[]) => Promise<number>,
|
|
37
|
+
): PrismaRawClient => ({
|
|
38
|
+
$queryRawUnsafe: (sql, ...params) =>
|
|
39
|
+
query(sql, params).catch((error: unknown) => {
|
|
40
|
+
throw prismaError(error);
|
|
41
|
+
}),
|
|
42
|
+
$executeRawUnsafe: (sql, ...params) =>
|
|
43
|
+
execute(sql, params).catch((error: unknown) => {
|
|
44
|
+
throw prismaError(error);
|
|
45
|
+
}),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
/** Prisma's raw query API over PGlite, as the Prisma client answers it. */
|
|
49
|
+
export const pglitePrisma = (db: PGlite): PrismaTransactionalClient => {
|
|
50
|
+
const over = (runner: PGlite | Transaction) =>
|
|
51
|
+
raw(
|
|
52
|
+
async (sql, params) => (await runner.query(sql, params)).rows,
|
|
53
|
+
async (sql, params) =>
|
|
54
|
+
(await runner.query(sql, params)).affectedRows ?? 0,
|
|
55
|
+
);
|
|
56
|
+
return {
|
|
57
|
+
...over(db),
|
|
58
|
+
$transaction: (fn) => db.transaction((tx) => fn(over(tx))),
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Prisma's raw query API over `node:sqlite`. Like Prisma's SQLite client, it
|
|
64
|
+
* runs one operation at a time, and begins transactions deferred.
|
|
65
|
+
*/
|
|
66
|
+
export const sqlitePrisma = (db: DatabaseSync): PrismaTransactionalClient => {
|
|
67
|
+
const over = raw(
|
|
68
|
+
async (sql, params) => db.prepare(sql).all(...(params as SqliteValue[])),
|
|
69
|
+
async (sql, params) =>
|
|
70
|
+
Number(db.prepare(sql).run(...(params as SqliteValue[])).changes),
|
|
71
|
+
);
|
|
72
|
+
let queue: Promise<unknown> = Promise.resolve();
|
|
73
|
+
const serial = <T>(task: () => Promise<T>) => {
|
|
74
|
+
const result = queue.then(task);
|
|
75
|
+
queue = result.catch(() => undefined);
|
|
76
|
+
return result;
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
$queryRawUnsafe: (sql, ...params) =>
|
|
80
|
+
serial(() => over.$queryRawUnsafe(sql, ...params)),
|
|
81
|
+
$executeRawUnsafe: (sql, ...params) =>
|
|
82
|
+
serial(() => over.$executeRawUnsafe(sql, ...params)),
|
|
83
|
+
$transaction: (fn) =>
|
|
84
|
+
serial(async () => {
|
|
85
|
+
db.exec("BEGIN");
|
|
86
|
+
try {
|
|
87
|
+
const result = await fn(over);
|
|
88
|
+
db.exec("COMMIT");
|
|
89
|
+
return result;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
db.exec("ROLLBACK");
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}),
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/** Prisma's raw query API over a mysql2 pool. */
|
|
99
|
+
export const mysqlPrisma = (pool: MysqlPool): PrismaTransactionalClient => {
|
|
100
|
+
const over = (runner: MysqlPool | PoolConnection) =>
|
|
101
|
+
raw(
|
|
102
|
+
async (sql, params) => (await runner.query(sql, params))[0] as unknown[],
|
|
103
|
+
async (sql, params) => {
|
|
104
|
+
const [result] = await runner.query(sql, params);
|
|
105
|
+
return (result as { affectedRows: number }).affectedRows;
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
return {
|
|
109
|
+
...over(pool),
|
|
110
|
+
async $transaction(fn) {
|
|
111
|
+
const connection = await pool.getConnection();
|
|
112
|
+
try {
|
|
113
|
+
await connection.beginTransaction();
|
|
114
|
+
const result = await fn(over(connection));
|
|
115
|
+
await connection.commit();
|
|
116
|
+
return result;
|
|
117
|
+
} catch (error) {
|
|
118
|
+
await connection.rollback().catch(() => undefined);
|
|
119
|
+
throw error;
|
|
120
|
+
} finally {
|
|
121
|
+
connection.release();
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const prismaCli = createRequire(import.meta.url).resolve(
|
|
128
|
+
"prisma/build/index.js",
|
|
129
|
+
);
|
|
130
|
+
const urls: Record<PrismaProvider, string> = {
|
|
131
|
+
sqlite: "file:./unused.db",
|
|
132
|
+
postgresql: "postgresql://unused@localhost/unused",
|
|
133
|
+
mysql: "mysql://unused@localhost/unused",
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/** The DDL `prisma db push` runs for the generated models on an empty database, from Prisma's CLI. */
|
|
137
|
+
export const prismaPushSql = async (
|
|
138
|
+
provider: PrismaProvider,
|
|
139
|
+
): Promise<string> => {
|
|
140
|
+
const directory = await mkdtemp(
|
|
141
|
+
path.join(os.tmpdir(), "hot-updater-prisma-"),
|
|
142
|
+
);
|
|
143
|
+
try {
|
|
144
|
+
const file = path.join(directory, "schema.prisma");
|
|
145
|
+
const models = prismaAdapter({ prisma: {}, provider }).generateSchema!(
|
|
146
|
+
"latest",
|
|
147
|
+
).code;
|
|
148
|
+
await writeFile(
|
|
149
|
+
file,
|
|
150
|
+
`datasource db {\n provider = "${provider}"\n url = "${urls[provider]}"\n}\n\n${models}\n`,
|
|
151
|
+
);
|
|
152
|
+
const { stdout } = await promisify(execFile)(
|
|
153
|
+
process.execPath,
|
|
154
|
+
[
|
|
155
|
+
prismaCli,
|
|
156
|
+
"migrate",
|
|
157
|
+
"diff",
|
|
158
|
+
"--from-empty",
|
|
159
|
+
"--to-schema-datamodel",
|
|
160
|
+
file,
|
|
161
|
+
"--script",
|
|
162
|
+
],
|
|
163
|
+
{
|
|
164
|
+
env: {
|
|
165
|
+
...process.env,
|
|
166
|
+
CHECKPOINT_DISABLE: "1",
|
|
167
|
+
PRISMA_HIDE_UPDATE_MESSAGE: "1",
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
);
|
|
171
|
+
return stdout;
|
|
172
|
+
} finally {
|
|
173
|
+
await rm(directory, { recursive: true, force: true });
|
|
174
|
+
}
|
|
175
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { sqlProviders, type ORMSQLProvider } from "../db/types";
|
|
2
|
+
|
|
3
|
+
/** The provider an adapter was given, when Hot Updater's SQL core runs on it. */
|
|
4
|
+
export const checkSqlProvider = <TProvider extends ORMSQLProvider>(
|
|
5
|
+
adapter: string,
|
|
6
|
+
provider: TProvider,
|
|
7
|
+
): TProvider => {
|
|
8
|
+
if (!(sqlProviders as readonly string[]).includes(provider)) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
`${adapter}: provider "${String(provider)}" is not supported. Use ${sqlProviders.map((name) => `"${name}"`).join(", ")}; CockroachDB and SQL Server were dropped in 1.0.`,
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
return provider;
|
|
14
|
+
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { describe, expect, it
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
2
|
|
|
3
|
-
import { createInMemoryDatabasePlugin } from "../../test-utils/test/inMemoryDatabasePlugin";
|
|
4
|
-
import { registerApiKey } from "./apiKeys";
|
|
5
3
|
import { API_KEY_HEADER_NAME, createHotUpdater } from "./index";
|
|
4
|
+
import { apiKeys } from "./plugins/api-keys";
|
|
5
|
+
import { insights } from "./plugins/insights";
|
|
6
|
+
import { createRuntimeDatabase } from "./runtime.testFixtures";
|
|
6
7
|
|
|
7
8
|
const API_KEY = "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE";
|
|
8
9
|
const updateUrl =
|
|
@@ -18,30 +19,19 @@ const withApiKey = (url: string, init?: RequestInit) =>
|
|
|
18
19
|
},
|
|
19
20
|
});
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
headerName: "invalid header",
|
|
27
|
-
type: "api-key",
|
|
28
|
-
},
|
|
29
|
-
database: createInMemoryDatabasePlugin(),
|
|
30
|
-
}),
|
|
31
|
-
).toThrow("clientAccess.headerName must be a valid header name.");
|
|
22
|
+
/** A server whose client routes the apiKeys() plugin protects, with one registered key. */
|
|
23
|
+
const start = async () => {
|
|
24
|
+
const hotUpdater = createHotUpdater({
|
|
25
|
+
database: createRuntimeDatabase(),
|
|
26
|
+
plugins: [apiKeys(), insights()],
|
|
32
27
|
});
|
|
28
|
+
await hotUpdater.api.apiKeys.register({ apiKey: API_KEY, name: "App" });
|
|
29
|
+
return hotUpdater;
|
|
30
|
+
};
|
|
33
31
|
|
|
32
|
+
describe("createHotUpdater with the apiKeys() plugin", () => {
|
|
34
33
|
it("protects only client OTA and Insights write routes", async () => {
|
|
35
|
-
const
|
|
36
|
-
await registerApiKey({
|
|
37
|
-
apiKeys: database.models.apiKeys,
|
|
38
|
-
apiKey: API_KEY,
|
|
39
|
-
name: "App",
|
|
40
|
-
});
|
|
41
|
-
const hotUpdater = createHotUpdater({
|
|
42
|
-
clientAccess: { type: "api-key" },
|
|
43
|
-
database,
|
|
44
|
-
});
|
|
34
|
+
const hotUpdater = await start();
|
|
45
35
|
|
|
46
36
|
expect(
|
|
47
37
|
(await hotUpdater.handlers.client(new Request(updateUrl))).status,
|
|
@@ -59,44 +49,14 @@ describe("createHotUpdater API keys", () => {
|
|
|
59
49
|
expect(
|
|
60
50
|
(
|
|
61
51
|
await hotUpdater.handlers.admin(
|
|
62
|
-
|
|
52
|
+
new Request("https://example.com/events"),
|
|
63
53
|
)
|
|
64
54
|
).status,
|
|
65
55
|
).toBe(200);
|
|
66
56
|
});
|
|
67
57
|
|
|
68
|
-
it("creates, lists, and revokes API keys without exposing hashes", async () => {
|
|
69
|
-
const hotUpdater = createHotUpdater({
|
|
70
|
-
clientAccess: { type: "public" },
|
|
71
|
-
database: createInMemoryDatabasePlugin(),
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
const created = await hotUpdater.apiKeys.create({ name: "Production" });
|
|
75
|
-
expect(created.apiKey).toMatch(/^[A-Za-z0-9_-]{43}$/u);
|
|
76
|
-
expect(created.record).not.toHaveProperty("hash");
|
|
77
|
-
|
|
78
|
-
await expect(hotUpdater.apiKeys.list()).resolves.toEqual([created.record]);
|
|
79
|
-
const revoked = await hotUpdater.apiKeys.revoke({
|
|
80
|
-
id: created.record.id,
|
|
81
|
-
});
|
|
82
|
-
expect(revoked).toMatchObject({
|
|
83
|
-
id: created.record.id,
|
|
84
|
-
revoked_at_ms: expect.any(Number),
|
|
85
|
-
});
|
|
86
|
-
expect(revoked).not.toHaveProperty("hash");
|
|
87
|
-
});
|
|
88
|
-
|
|
89
58
|
it("authenticates before parsing Insights event bodies", async () => {
|
|
90
|
-
const
|
|
91
|
-
await registerApiKey({
|
|
92
|
-
apiKeys: database.models.apiKeys,
|
|
93
|
-
apiKey: API_KEY,
|
|
94
|
-
name: "App",
|
|
95
|
-
});
|
|
96
|
-
const hotUpdater = createHotUpdater({
|
|
97
|
-
clientAccess: { type: "api-key" },
|
|
98
|
-
database,
|
|
99
|
-
});
|
|
59
|
+
const hotUpdater = await start();
|
|
100
60
|
const invalidBody = {
|
|
101
61
|
method: "POST",
|
|
102
62
|
headers: { "content-type": "application/json" },
|
|
@@ -119,74 +79,14 @@ describe("createHotUpdater API keys", () => {
|
|
|
119
79
|
).toBe(400);
|
|
120
80
|
});
|
|
121
81
|
|
|
122
|
-
it(
|
|
123
|
-
const database = createInMemoryDatabasePlugin();
|
|
124
|
-
vi.spyOn(database.models.apiKeys, "findByHash").mockRejectedValue(
|
|
125
|
-
new Error("database offline"),
|
|
126
|
-
);
|
|
82
|
+
it('keeps client routes public with clientAccess: "public"', async () => {
|
|
127
83
|
const hotUpdater = createHotUpdater({
|
|
128
|
-
clientAccess:
|
|
129
|
-
database,
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
const response = await hotUpdater.handlers.client(withApiKey(updateUrl));
|
|
133
|
-
|
|
134
|
-
expect(response.status).toBe(503);
|
|
135
|
-
await expect(response.json()).resolves.toEqual({
|
|
136
|
-
error: "Service unavailable",
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it("keeps client routes public with the public access policy", async () => {
|
|
141
|
-
const hotUpdater = createHotUpdater({
|
|
142
|
-
clientAccess: { type: "public" },
|
|
143
|
-
database: createInMemoryDatabasePlugin(),
|
|
84
|
+
clientAccess: "public",
|
|
85
|
+
database: createRuntimeDatabase(),
|
|
144
86
|
});
|
|
145
87
|
|
|
146
88
|
expect(
|
|
147
89
|
(await hotUpdater.handlers.client(new Request(updateUrl))).status,
|
|
148
90
|
).toBe(404);
|
|
149
91
|
});
|
|
150
|
-
|
|
151
|
-
it("reads API keys only from the configured header", async () => {
|
|
152
|
-
const database = createInMemoryDatabasePlugin();
|
|
153
|
-
await registerApiKey({
|
|
154
|
-
apiKeys: database.models.apiKeys,
|
|
155
|
-
apiKey: API_KEY,
|
|
156
|
-
name: "App",
|
|
157
|
-
});
|
|
158
|
-
const hotUpdater = createHotUpdater({
|
|
159
|
-
clientAccess: {
|
|
160
|
-
headerName: "X-Hot-Updater-Key",
|
|
161
|
-
type: "api-key",
|
|
162
|
-
},
|
|
163
|
-
database,
|
|
164
|
-
});
|
|
165
|
-
const invalidBody = {
|
|
166
|
-
method: "POST",
|
|
167
|
-
headers: { "content-type": "application/json" },
|
|
168
|
-
body: "not-json",
|
|
169
|
-
} satisfies RequestInit;
|
|
170
|
-
|
|
171
|
-
expect(
|
|
172
|
-
(
|
|
173
|
-
await hotUpdater.handlers.client(
|
|
174
|
-
withApiKey("https://example.com/events", invalidBody),
|
|
175
|
-
)
|
|
176
|
-
).status,
|
|
177
|
-
).toBe(401);
|
|
178
|
-
expect(
|
|
179
|
-
(
|
|
180
|
-
await hotUpdater.handlers.client(
|
|
181
|
-
new Request("https://example.com/events", {
|
|
182
|
-
...invalidBody,
|
|
183
|
-
headers: {
|
|
184
|
-
...invalidBody.headers,
|
|
185
|
-
"x-hot-updater-key": API_KEY,
|
|
186
|
-
},
|
|
187
|
-
}),
|
|
188
|
-
)
|
|
189
|
-
).status,
|
|
190
|
-
).toBe(400);
|
|
191
|
-
});
|
|
192
92
|
});
|
package/src/apiKeys.spec.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createMemoryAdapter } from "@hot-updater/plugin-core/internal";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
2
3
|
|
|
3
|
-
import { createInMemoryDatabasePlugin } from "../../test-utils/test/inMemoryDatabasePlugin";
|
|
4
4
|
import {
|
|
5
5
|
API_KEY_HEADER_NAME,
|
|
6
6
|
authenticateApiKey,
|
|
@@ -11,6 +11,20 @@ import {
|
|
|
11
11
|
provisionApiKey,
|
|
12
12
|
registerApiKey,
|
|
13
13
|
} from "./apiKeys";
|
|
14
|
+
import { createDatabaseEngine } from "./database/database";
|
|
15
|
+
import { resolveSchema } from "./database/resolveSchema";
|
|
16
|
+
import { apiKeysSchema, createApiKeyModel } from "./plugins/api-keys";
|
|
17
|
+
|
|
18
|
+
/** The api-keys plugin's table model on an empty in-memory database. */
|
|
19
|
+
const createModel = () => {
|
|
20
|
+
const module = { id: "apiKeys", schema: apiKeysSchema } as const;
|
|
21
|
+
return createApiKeyModel(
|
|
22
|
+
createDatabaseEngine({
|
|
23
|
+
adapter: createMemoryAdapter(),
|
|
24
|
+
schema: resolveSchema([module]),
|
|
25
|
+
}).database(module),
|
|
26
|
+
);
|
|
27
|
+
};
|
|
14
28
|
|
|
15
29
|
const API_KEY = "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE";
|
|
16
30
|
|
|
@@ -21,18 +35,18 @@ describe("API keys", () => {
|
|
|
21
35
|
"x-hot-updater-key",
|
|
22
36
|
);
|
|
23
37
|
expect(() => normalizeApiKeyHeaderName("")).toThrow(
|
|
24
|
-
"
|
|
38
|
+
"apiKeys({ headerName }) must name a valid header.",
|
|
25
39
|
);
|
|
26
40
|
expect(() => normalizeApiKeyHeaderName("invalid header")).toThrow(
|
|
27
|
-
"
|
|
41
|
+
"apiKeys({ headerName }) must name a valid header.",
|
|
28
42
|
);
|
|
29
43
|
});
|
|
30
44
|
|
|
31
45
|
it("persists only the digest and metadata for a registered key", async () => {
|
|
32
|
-
const
|
|
46
|
+
const model = createModel();
|
|
33
47
|
|
|
34
48
|
const created = await registerApiKey({
|
|
35
|
-
apiKeys:
|
|
49
|
+
apiKeys: model,
|
|
36
50
|
apiKey: API_KEY,
|
|
37
51
|
createdAtMs: 100,
|
|
38
52
|
name: " Production app ",
|
|
@@ -49,28 +63,25 @@ describe("API keys", () => {
|
|
|
49
63
|
});
|
|
50
64
|
expect(created.record).not.toHaveProperty("hash");
|
|
51
65
|
expect(created.record.id).not.toContain(await hashApiKey(API_KEY));
|
|
52
|
-
expect(await
|
|
66
|
+
expect(await model.list()).toEqual([
|
|
53
67
|
expect.objectContaining({ hash: await hashApiKey(API_KEY) }),
|
|
54
68
|
]);
|
|
55
|
-
expect(JSON.stringify(await
|
|
56
|
-
API_KEY,
|
|
57
|
-
);
|
|
69
|
+
expect(JSON.stringify(await model.list())).not.toContain(API_KEY);
|
|
58
70
|
|
|
59
71
|
const registeredAgain = await registerApiKey({
|
|
60
|
-
apiKeys:
|
|
72
|
+
apiKeys: model,
|
|
61
73
|
apiKey: API_KEY,
|
|
62
74
|
createdAtMs: 200,
|
|
63
75
|
name: "Ignored replacement name",
|
|
64
76
|
});
|
|
65
77
|
expect(registeredAgain.record).toEqual(created.record);
|
|
66
|
-
expect(await
|
|
78
|
+
expect(await model.list()).toHaveLength(1);
|
|
67
79
|
});
|
|
68
80
|
|
|
69
|
-
it("authenticates only active keys
|
|
70
|
-
const
|
|
71
|
-
const beforeLookup = vi.fn(async () => undefined);
|
|
81
|
+
it("authenticates only active keys", async () => {
|
|
82
|
+
const model = createModel();
|
|
72
83
|
const { record } = await registerApiKey({
|
|
73
|
-
apiKeys:
|
|
84
|
+
apiKeys: model,
|
|
74
85
|
apiKey: API_KEY,
|
|
75
86
|
name: "App",
|
|
76
87
|
});
|
|
@@ -80,30 +91,28 @@ describe("API keys", () => {
|
|
|
80
91
|
|
|
81
92
|
await expect(
|
|
82
93
|
authenticateApiKey({
|
|
83
|
-
apiKeys:
|
|
84
|
-
beforeLookup,
|
|
94
|
+
apiKeys: model,
|
|
85
95
|
request,
|
|
86
96
|
}),
|
|
87
97
|
).resolves.toBe(true);
|
|
88
|
-
expect(beforeLookup).toHaveBeenCalledOnce();
|
|
89
98
|
|
|
90
|
-
await
|
|
99
|
+
await model.revoke({
|
|
91
100
|
id: record.id,
|
|
92
101
|
revokedAtMs: Date.now(),
|
|
93
102
|
});
|
|
94
103
|
await expect(
|
|
95
104
|
authenticateApiKey({
|
|
96
|
-
apiKeys:
|
|
105
|
+
apiKeys: model,
|
|
97
106
|
request,
|
|
98
107
|
}),
|
|
99
108
|
).resolves.toBe(false);
|
|
100
109
|
});
|
|
101
110
|
|
|
102
111
|
it("creates a canonical key and validates visible names", async () => {
|
|
103
|
-
const
|
|
112
|
+
const model = createModel();
|
|
104
113
|
|
|
105
114
|
const created = await createApiKey({
|
|
106
|
-
apiKeys:
|
|
115
|
+
apiKeys: model,
|
|
107
116
|
name: "App",
|
|
108
117
|
});
|
|
109
118
|
|
|
@@ -111,7 +120,7 @@ describe("API keys", () => {
|
|
|
111
120
|
expect(created.record.prefix).toBe(created.apiKey.slice(0, 6));
|
|
112
121
|
await expect(
|
|
113
122
|
registerApiKey({
|
|
114
|
-
apiKeys:
|
|
123
|
+
apiKeys: model,
|
|
115
124
|
apiKey: API_KEY,
|
|
116
125
|
name: " ",
|
|
117
126
|
}),
|
|
@@ -119,29 +128,25 @@ describe("API keys", () => {
|
|
|
119
128
|
});
|
|
120
129
|
|
|
121
130
|
it("provisions a new key once and reuses an existing managed key", async () => {
|
|
122
|
-
const
|
|
131
|
+
const model = createModel();
|
|
123
132
|
|
|
124
133
|
const created = await provisionApiKey({
|
|
125
|
-
apiKeys:
|
|
134
|
+
apiKeys: model,
|
|
126
135
|
name: "Managed init",
|
|
127
136
|
});
|
|
128
137
|
const reused = await provisionApiKey({
|
|
129
|
-
apiKeys:
|
|
138
|
+
apiKeys: model,
|
|
130
139
|
existingApiKey: created.apiKey,
|
|
131
140
|
name: "Managed init rerun",
|
|
132
141
|
});
|
|
133
142
|
|
|
134
143
|
expect(reused).toEqual(created);
|
|
135
|
-
expect(await
|
|
144
|
+
expect(await model.list()).toHaveLength(1);
|
|
136
145
|
});
|
|
137
146
|
|
|
138
147
|
it("manages keys without exposing stored hashes", async () => {
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
const apiKeys = createApiKeyManagement({
|
|
142
|
-
apiKeys: database.models.apiKeys,
|
|
143
|
-
beforeOperation,
|
|
144
|
-
});
|
|
148
|
+
const model = createModel();
|
|
149
|
+
const apiKeys = createApiKeyManagement({ apiKeys: model });
|
|
145
150
|
|
|
146
151
|
const created = await apiKeys.create({ name: "Production app" });
|
|
147
152
|
expect(created.apiKey).toMatch(/^[A-Za-z0-9_-]{43}$/u);
|
|
@@ -157,6 +162,5 @@ describe("API keys", () => {
|
|
|
157
162
|
revoked_at_ms: expect.any(Number),
|
|
158
163
|
});
|
|
159
164
|
expect(revoked).not.toHaveProperty("hash");
|
|
160
|
-
expect(beforeOperation).toHaveBeenCalledTimes(3);
|
|
161
165
|
});
|
|
162
166
|
});
|
package/src/apiKeys.ts
CHANGED
|
@@ -32,7 +32,7 @@ export const normalizeApiKeyHeaderName = (
|
|
|
32
32
|
value: unknown = API_KEY_HEADER_NAME,
|
|
33
33
|
): string => {
|
|
34
34
|
if (typeof value !== "string" || value.length === 0) {
|
|
35
|
-
throw new TypeError("
|
|
35
|
+
throw new TypeError("apiKeys({ headerName }) must name a valid header.");
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
try {
|
|
@@ -40,7 +40,7 @@ export const normalizeApiKeyHeaderName = (
|
|
|
40
40
|
headers.set(value, "");
|
|
41
41
|
return headers.keys().next().value!;
|
|
42
42
|
} catch {
|
|
43
|
-
throw new TypeError("
|
|
43
|
+
throw new TypeError("apiKeys({ headerName }) must name a valid header.");
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
|
|
@@ -172,7 +172,6 @@ export const provisionApiKey = (input: {
|
|
|
172
172
|
};
|
|
173
173
|
|
|
174
174
|
export const authenticateApiKey = async (input: {
|
|
175
|
-
readonly beforeLookup?: () => Promise<void>;
|
|
176
175
|
readonly apiKeys: ApiKeyModel;
|
|
177
176
|
readonly headerName?: string;
|
|
178
177
|
readonly request: Request;
|
|
@@ -182,7 +181,6 @@ export const authenticateApiKey = async (input: {
|
|
|
182
181
|
);
|
|
183
182
|
if (apiKey === null || !isApiKey(apiKey)) return false;
|
|
184
183
|
const hash = await hashApiKey(apiKey);
|
|
185
|
-
await input.beforeLookup?.();
|
|
186
184
|
const record = await input.apiKeys.findByHash(hash);
|
|
187
185
|
return (
|
|
188
186
|
record !== null &&
|
|
@@ -194,11 +192,9 @@ export const authenticateApiKey = async (input: {
|
|
|
194
192
|
|
|
195
193
|
export const createApiKeyManagement = (input: {
|
|
196
194
|
readonly apiKeys: ApiKeyModel;
|
|
197
|
-
readonly beforeOperation: () => Promise<void>;
|
|
198
195
|
}): ApiKeyManagementAPI =>
|
|
199
196
|
Object.freeze({
|
|
200
197
|
async create({ name }: { readonly name: string }) {
|
|
201
|
-
await input.beforeOperation();
|
|
202
198
|
const created = await createApiKey({ apiKeys: input.apiKeys, name });
|
|
203
199
|
return Object.freeze({
|
|
204
200
|
apiKey: created.apiKey,
|
|
@@ -206,11 +202,9 @@ export const createApiKeyManagement = (input: {
|
|
|
206
202
|
});
|
|
207
203
|
},
|
|
208
204
|
async list() {
|
|
209
|
-
await input.beforeOperation();
|
|
210
205
|
return Object.freeze((await input.apiKeys.list()).map(toApiKeyMetadata));
|
|
211
206
|
},
|
|
212
207
|
async revoke({ id }: { readonly id: string }) {
|
|
213
|
-
await input.beforeOperation();
|
|
214
208
|
const record = await input.apiKeys.revoke({
|
|
215
209
|
id,
|
|
216
210
|
revokedAtMs: Date.now(),
|