@hot-updater/server 1.0.0-rc.18 → 1.0.0-rc.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +12 -14
- package/dist/adapters/drizzle.cjs +6 -8
- package/dist/adapters/drizzle.d.cts +2 -2
- package/dist/adapters/drizzle.d.mts +2 -2
- package/dist/adapters/drizzle.mjs +1 -3
- package/dist/adapters/drizzleExecutor.d.cts +1 -1
- package/dist/adapters/drizzleExecutor.d.mts +1 -1
- package/dist/adapters/kysely.cjs +4 -6
- package/dist/adapters/kysely.d.cts +3 -3
- package/dist/adapters/kysely.d.mts +3 -3
- package/dist/adapters/kysely.mjs +1 -3
- package/dist/adapters/kyselyExecutor.d.cts +1 -2
- package/dist/adapters/kyselyExecutor.d.mts +1 -2
- package/dist/adapters/mongodb.cjs +10 -21
- package/dist/adapters/mongodb.d.cts +1 -1
- package/dist/adapters/mongodb.d.mts +1 -1
- package/dist/adapters/mongodb.mjs +9 -20
- package/dist/adapters/mongodbAdapter.cjs +11 -11
- package/dist/adapters/mongodbAdapter.d.cts +1 -1
- package/dist/adapters/mongodbAdapter.d.mts +1 -1
- package/dist/adapters/mongodbAdapter.mjs +1 -1
- package/dist/adapters/prisma.cjs +7 -9
- package/dist/adapters/prisma.d.cts +1 -1
- package/dist/adapters/prisma.d.mts +1 -1
- package/dist/adapters/prisma.mjs +1 -3
- package/dist/adapters/prismaExecutor.cjs +2 -3
- package/dist/adapters/prismaExecutor.mjs +1 -2
- package/dist/adapters/sqlProviders.cjs +7 -2
- package/dist/adapters/sqlProviders.mjs +6 -1
- package/dist/assembly/assemblePlugins.cjs +26 -48
- package/dist/assembly/assemblePlugins.d.cts +2 -5
- package/dist/assembly/assemblePlugins.d.mts +2 -5
- package/dist/assembly/assemblePlugins.mjs +19 -45
- package/dist/assembly/clientPlugins.cjs +6 -4
- package/dist/assembly/clientPlugins.mjs +2 -0
- package/dist/assembly/configError.d.cts +1 -6
- package/dist/assembly/configError.d.mts +1 -6
- package/dist/assembly/configError.mjs +1 -6
- package/dist/core/api.cjs +0 -40
- package/dist/core/api.d.cts +5 -16
- package/dist/core/api.d.mts +5 -16
- package/dist/core/api.mjs +1 -37
- package/dist/core/baseCandidates.cjs +0 -43
- package/dist/core/baseCandidates.mjs +2 -43
- package/dist/core/operations.cjs +13 -12
- package/dist/core/operations.mjs +6 -5
- package/dist/core/reads.cjs +4 -4
- package/dist/core/reads.d.cts +2 -41
- package/dist/core/reads.d.mts +2 -41
- package/dist/core/reads.mjs +3 -3
- package/dist/core/releases.cjs +6 -6
- package/dist/core/releases.mjs +1 -1
- package/dist/core/writes.cjs +2 -2
- package/dist/core/writes.mjs +1 -1
- package/dist/createHotUpdaterCore.cjs +39 -39
- package/dist/createHotUpdaterCore.d.cts +61 -8
- package/dist/createHotUpdaterCore.d.mts +61 -8
- package/dist/createHotUpdaterCore.mjs +35 -32
- package/dist/db/engineDrizzleSchema.cjs +3 -4
- package/dist/db/engineDrizzleSchema.mjs +1 -2
- package/dist/db/enginePrismaSchema.cjs +4 -5
- package/dist/db/enginePrismaSchema.d.cts +1 -1
- package/dist/db/enginePrismaSchema.d.mts +1 -1
- package/dist/db/enginePrismaSchema.mjs +1 -2
- package/dist/db/releaseCatalog.cjs +6 -6
- package/dist/db/releaseCatalog.mjs +1 -1
- package/dist/db/updateArtifacts.cjs +6 -6
- package/dist/db/updateArtifacts.mjs +1 -1
- package/dist/handler.cjs +3 -4
- package/dist/handler.mjs +1 -1
- package/dist/handlerAdminRoutes.cjs +1 -2
- package/dist/handlerAdminRoutes.mjs +1 -2
- package/dist/handlerVersionRoutes.cjs +2 -2
- package/dist/handlerVersionRoutes.mjs +2 -2
- package/dist/index.cjs +9 -2
- package/dist/index.d.cts +4 -3
- package/dist/index.d.mts +4 -3
- package/dist/index.mjs +2 -1
- package/dist/node.cjs +3 -6
- package/dist/node.d.cts +3 -3
- package/dist/node.d.mts +3 -3
- package/dist/node.mjs +4 -4
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/plugins/api-keys/index.cjs +8 -52
- package/dist/plugins/api-keys/index.d.cts +1 -84
- package/dist/plugins/api-keys/index.d.mts +1 -84
- package/dist/plugins/api-keys/index.mjs +2 -49
- package/dist/plugins/definePlugin.d.cts +2 -200
- package/dist/plugins/definePlugin.d.mts +2 -200
- package/dist/plugins/insights/index.cjs +7 -126
- package/dist/plugins/insights/index.d.cts +1 -398
- package/dist/plugins/insights/index.d.mts +1 -398
- package/dist/plugins/insights/index.mjs +2 -121
- package/dist/plugins/official.cjs +30 -0
- package/dist/plugins/official.mjs +29 -0
- package/dist/storageAccess.cjs +13 -10
- package/dist/storageAccess.mjs +13 -10
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.mts +1 -1
- package/package.json +15 -37
- package/dist/_virtual/_rolldown/runtime.cjs +0 -23
- package/dist/assembly/clientPlugins.d.cts +0 -16
- package/dist/assembly/clientPlugins.d.mts +0 -16
- package/dist/assembly/configError.cjs +0 -7
- package/dist/assembly/databasePlugins.cjs +0 -27
- package/dist/assembly/databasePlugins.d.cts +0 -43
- package/dist/assembly/databasePlugins.d.mts +0 -43
- package/dist/assembly/databasePlugins.mjs +0 -26
- package/dist/assembly/pluginCli.cjs +0 -125
- package/dist/assembly/pluginCli.d.cts +0 -59
- package/dist/assembly/pluginCli.d.mts +0 -59
- package/dist/assembly/pluginCli.mjs +0 -121
- package/dist/core/baseCandidates.d.cts +0 -17
- package/dist/core/baseCandidates.d.mts +0 -17
- package/dist/core/schema.cjs +0 -279
- package/dist/core/schema.d.cts +0 -307
- package/dist/core/schema.d.mts +0 -307
- package/dist/core/schema.mjs +0 -277
- package/dist/database/aggregateBatching.cjs +0 -626
- package/dist/database/aggregateBatching.d.cts +0 -10
- package/dist/database/aggregateBatching.d.mts +0 -10
- package/dist/database/aggregateBatching.mjs +0 -625
- package/dist/database/busy.cjs +0 -36
- package/dist/database/busy.d.cts +0 -12
- package/dist/database/busy.d.mts +0 -12
- package/dist/database/busy.mjs +0 -36
- package/dist/database/cursor.cjs +0 -44
- package/dist/database/cursor.d.cts +0 -7
- package/dist/database/cursor.d.mts +0 -7
- package/dist/database/cursor.mjs +0 -40
- package/dist/database/database.cjs +0 -63
- package/dist/database/database.d.cts +0 -136
- package/dist/database/database.d.mts +0 -136
- package/dist/database/database.mjs +0 -63
- package/dist/database/definitions.d.cts +0 -78
- package/dist/database/definitions.d.mts +0 -78
- package/dist/database/engine.cjs +0 -37
- package/dist/database/engine.d.cts +0 -41
- package/dist/database/engine.d.mts +0 -41
- package/dist/database/engine.mjs +0 -37
- package/dist/database/engineAggregates.cjs +0 -118
- package/dist/database/engineAggregates.mjs +0 -115
- package/dist/database/engineReads.cjs +0 -182
- package/dist/database/engineReads.d.cts +0 -35
- package/dist/database/engineReads.d.mts +0 -35
- package/dist/database/engineReads.mjs +0 -181
- package/dist/database/engineTransaction.cjs +0 -399
- package/dist/database/engineTransaction.d.cts +0 -26
- package/dist/database/engineTransaction.d.mts +0 -26
- package/dist/database/engineTransaction.mjs +0 -398
- package/dist/database/errors.cjs +0 -27
- package/dist/database/errors.d.cts +0 -21
- package/dist/database/errors.d.mts +0 -21
- package/dist/database/errors.mjs +0 -24
- package/dist/database/fence.cjs +0 -125
- package/dist/database/fence.d.cts +0 -42
- package/dist/database/fence.d.mts +0 -42
- package/dist/database/fence.mjs +0 -117
- package/dist/database/index.cjs +0 -136
- package/dist/database/index.d.cts +0 -18
- package/dist/database/index.d.mts +0 -18
- package/dist/database/index.mjs +0 -16
- package/dist/database/kv/kvAdapter.cjs +0 -285
- package/dist/database/kv/kvAdapter.d.cts +0 -109
- package/dist/database/kv/kvAdapter.d.mts +0 -109
- package/dist/database/kv/kvAdapter.mjs +0 -284
- package/dist/database/resolveSchema.cjs +0 -199
- package/dist/database/resolveSchema.d.cts +0 -42
- package/dist/database/resolveSchema.d.mts +0 -42
- package/dist/database/resolveSchema.mjs +0 -196
- package/dist/database/retention.cjs +0 -92
- package/dist/database/retention.mjs +0 -90
- package/dist/database/schema.cjs +0 -24
- package/dist/database/schema.d.cts +0 -90
- package/dist/database/schema.d.mts +0 -90
- package/dist/database/schema.mjs +0 -23
- package/dist/database/sql/sqlAdapter.cjs +0 -290
- package/dist/database/sql/sqlAdapter.d.cts +0 -46
- package/dist/database/sql/sqlAdapter.d.mts +0 -46
- package/dist/database/sql/sqlAdapter.mjs +0 -287
- package/dist/database/sql/sqlSchema.cjs +0 -171
- package/dist/database/sql/sqlSchema.d.cts +0 -8
- package/dist/database/sql/sqlSchema.d.mts +0 -8
- package/dist/database/sql/sqlSchema.mjs +0 -165
- package/dist/db/coreDatabase.cjs +0 -85
- package/dist/db/coreDatabase.d.cts +0 -57
- package/dist/db/coreDatabase.d.mts +0 -57
- package/dist/db/coreDatabase.mjs +0 -78
- package/dist/db/createBundleDiff.cjs +0 -144
- package/dist/db/createBundleDiff.d.cts +0 -17
- package/dist/db/createBundleDiff.d.mts +0 -17
- package/dist/db/createBundleDiff.mjs +0 -141
- package/dist/db/engineMigrator.cjs +0 -53
- package/dist/db/engineMigrator.mjs +0 -53
- package/dist/db/engineSql.cjs +0 -26
- package/dist/db/engineSql.d.cts +0 -17
- package/dist/db/engineSql.d.mts +0 -17
- package/dist/db/engineSql.mjs +0 -25
- package/dist/db/engineSqlMigrator.cjs +0 -66
- package/dist/db/engineSqlMigrator.mjs +0 -66
- package/dist/db/fixedMigratorShared.cjs +0 -12
- package/dist/db/fixedMigratorShared.mjs +0 -11
- package/dist/db/index.cjs +0 -50
- package/dist/db/index.d.cts +0 -23
- package/dist/db/index.d.mts +0 -23
- package/dist/db/index.mjs +0 -33
- package/dist/db/releaseCatalog.d.cts +0 -16
- package/dist/db/releaseCatalog.d.mts +0 -16
- package/dist/db/schemaSettings.cjs +0 -63
- package/dist/db/schemaSettings.d.cts +0 -12
- package/dist/db/schemaSettings.d.mts +0 -12
- package/dist/db/schemaSettings.mjs +0 -62
- package/dist/db/settingsMigrator.cjs +0 -92
- package/dist/db/settingsMigrator.mjs +0 -89
- package/dist/db/types.cjs +0 -11
- package/dist/db/types.d.cts +0 -78
- package/dist/db/types.d.mts +0 -78
- package/dist/db/types.mjs +0 -10
- package/dist/diff.cjs +0 -3
- package/dist/diff.d.cts +0 -2
- package/dist/diff.d.mts +0 -2
- package/dist/diff.mjs +0 -2
- package/dist/plugins/api-keys/apiKeys.cjs +0 -139
- package/dist/plugins/api-keys/apiKeys.d.cts +0 -27
- package/dist/plugins/api-keys/apiKeys.d.mts +0 -27
- package/dist/plugins/api-keys/apiKeys.mjs +0 -129
- package/dist/plugins/api-keys/cli.cjs +0 -115
- package/dist/plugins/api-keys/cli.mjs +0 -114
- package/dist/plugins/api-keys/model.cjs +0 -58
- package/dist/plugins/api-keys/model.d.cts +0 -26
- package/dist/plugins/api-keys/model.d.mts +0 -26
- package/dist/plugins/api-keys/model.mjs +0 -58
- package/dist/plugins/api-keys/schema.cjs +0 -38
- package/dist/plugins/api-keys/schema.d.cts +0 -44
- package/dist/plugins/api-keys/schema.d.mts +0 -44
- package/dist/plugins/api-keys/schema.mjs +0 -39
- package/dist/plugins/definePlugin.cjs +0 -5
- package/dist/plugins/definePlugin.mjs +0 -5
- package/dist/plugins/index.cjs +0 -38
- package/dist/plugins/index.d.cts +0 -12
- package/dist/plugins/index.d.mts +0 -12
- package/dist/plugins/index.mjs +0 -9
- package/dist/plugins/insights/contract.cjs +0 -193
- package/dist/plugins/insights/contract.mjs +0 -189
- package/dist/plugins/insights/domain.d.cts +0 -149
- package/dist/plugins/insights/domain.d.mts +0 -149
- package/dist/plugins/insights/errors.cjs +0 -15
- package/dist/plugins/insights/errors.mjs +0 -14
- package/dist/plugins/insights/eventInput.cjs +0 -284
- package/dist/plugins/insights/eventInput.mjs +0 -282
- package/dist/plugins/insights/eventRow.cjs +0 -49
- package/dist/plugins/insights/eventRow.d.cts +0 -64
- package/dist/plugins/insights/eventRow.d.mts +0 -64
- package/dist/plugins/insights/eventRow.mjs +0 -47
- package/dist/plugins/insights/model.cjs +0 -17
- package/dist/plugins/insights/model.d.cts +0 -10
- package/dist/plugins/insights/model.d.mts +0 -10
- package/dist/plugins/insights/model.mjs +0 -17
- package/dist/plugins/insights/modelTypes.d.cts +0 -176
- package/dist/plugins/insights/modelTypes.d.mts +0 -176
- package/dist/plugins/insights/overview.cjs +0 -109
- package/dist/plugins/insights/overview.d.cts +0 -15
- package/dist/plugins/insights/overview.d.mts +0 -15
- package/dist/plugins/insights/overview.mjs +0 -107
- package/dist/plugins/insights/provider.cjs +0 -375
- package/dist/plugins/insights/provider.d.cts +0 -6
- package/dist/plugins/insights/provider.d.mts +0 -6
- package/dist/plugins/insights/provider.mjs +0 -374
- package/dist/plugins/insights/queryInput.cjs +0 -93
- package/dist/plugins/insights/queryInput.mjs +0 -91
- package/dist/plugins/insights/reads.cjs +0 -681
- package/dist/plugins/insights/reads.d.cts +0 -61
- package/dist/plugins/insights/reads.d.mts +0 -61
- package/dist/plugins/insights/reads.mjs +0 -674
- package/dist/plugins/insights/recordEvent.cjs +0 -319
- package/dist/plugins/insights/recordEvent.d.cts +0 -18
- package/dist/plugins/insights/recordEvent.d.mts +0 -18
- package/dist/plugins/insights/recordEvent.mjs +0 -316
- package/dist/plugins/insights/routes.cjs +0 -96
- package/dist/plugins/insights/routes.mjs +0 -95
- package/dist/plugins/insights/schema.cjs +0 -489
- package/dist/plugins/insights/schema.d.cts +0 -698
- package/dist/plugins/insights/schema.d.mts +0 -698
- package/dist/plugins/insights/schema.mjs +0 -483
- package/dist/plugins/insights/testing/eventRow.d.mts +0 -64
- package/dist/plugins/insights/testing/expectInsightsIndex.mjs +0 -18
- package/dist/plugins/insights/testing/fixtures.d.mts +0 -8
- package/dist/plugins/insights/testing/fixtures.mjs +0 -25
- package/dist/plugins/insights/testing/index.d.mts +0 -24
- package/dist/plugins/insights/testing/index.mjs +0 -25
- package/dist/plugins/insights/testing/insightsModelTests.mjs +0 -714
- package/dist/plugins/insights/testing/modelTypes.d.mts +0 -176
- package/dist/plugins/insights/testing/setupInsightsHttpTestSuite.d.mts +0 -11
- package/dist/plugins/insights/testing/setupInsightsHttpTestSuite.mjs +0 -107
- package/dist/plugins/insights/testing/setupInsightsModelTestSuite.d.mts +0 -11
- package/dist/plugins/insights/testing/setupInsightsModelTestSuite.mjs +0 -31
- package/dist/plugins/insights/testing/types.d.mts +0 -26
- package/dist/plugins/insights/types.d.cts +0 -33
- package/dist/plugins/insights/types.d.mts +0 -33
- package/src/adapters/drizzle.conformance.integration.spec.ts +0 -34
- package/src/adapters/drizzle.readBudgets.integration.spec.ts +0 -43
- package/src/adapters/drizzle.spec.ts +0 -314
- package/src/adapters/drizzle.ts +0 -64
- package/src/adapters/drizzleExecutor.ts +0 -166
- package/src/adapters/kysely.conformance.integration.spec.ts +0 -36
- package/src/adapters/kysely.readBudgets.integration.spec.ts +0 -44
- package/src/adapters/kysely.spec.ts +0 -244
- package/src/adapters/kysely.ts +0 -46
- package/src/adapters/kyselyExecutor.ts +0 -53
- package/src/adapters/mongodb.integration.spec.ts +0 -271
- package/src/adapters/mongodb.readBudgets.integration.spec.ts +0 -61
- package/src/adapters/mongodb.ts +0 -45
- package/src/adapters/mongodbAdapter.ts +0 -307
- package/src/adapters/prisma.conformance.integration.spec.ts +0 -36
- package/src/adapters/prisma.integration.spec.ts +0 -146
- package/src/adapters/prisma.readBudgets.integration.spec.ts +0 -43
- package/src/adapters/prisma.spec.ts +0 -257
- package/src/adapters/prisma.ts +0 -74
- package/src/adapters/prismaExecutor.ts +0 -107
- package/src/adapters/prismaTestClients.ts +0 -182
- package/src/adapters/sqlProviders.ts +0 -14
- package/src/assembly/assemblePlugins.ts +0 -302
- package/src/assembly/assembly.spec.ts +0 -377
- package/src/assembly/assembly.types.spec.ts +0 -203
- package/src/assembly/clientPlugins.ts +0 -113
- package/src/assembly/configError.ts +0 -4
- package/src/assembly/databasePlugins.spec.ts +0 -71
- package/src/assembly/databasePlugins.ts +0 -102
- package/src/assembly/pluginCli.spec.ts +0 -254
- package/src/assembly/pluginCli.ts +0 -248
- package/src/assembly/pluginRoutes.spec.ts +0 -186
- package/src/core/api.ts +0 -139
- package/src/core/baseCandidates.spec.ts +0 -378
- package/src/core/baseCandidates.ts +0 -136
- package/src/core/index.ts +0 -44
- package/src/core/operations.spec.ts +0 -415
- package/src/core/operations.ts +0 -551
- package/src/core/reads.spec.ts +0 -300
- package/src/core/reads.ts +0 -417
- package/src/core/releases.spec.ts +0 -308
- package/src/core/releases.ts +0 -345
- package/src/core/schema.ts +0 -173
- package/src/core/writes.ts +0 -160
- package/src/createHotUpdaterCore.ts +0 -260
- package/src/database/aggregateBatching.spec.ts +0 -577
- package/src/database/aggregateBatching.ts +0 -803
- package/src/database/busy.spec.ts +0 -45
- package/src/database/busy.ts +0 -50
- package/src/database/cursor.ts +0 -65
- package/src/database/database.ts +0 -366
- package/src/database/database.types.spec.ts +0 -135
- package/src/database/definitions.ts +0 -76
- package/src/database/engine.ts +0 -62
- package/src/database/engineAggregates.spec.ts +0 -536
- package/src/database/engineAggregates.ts +0 -189
- package/src/database/engineReads.spec.ts +0 -219
- package/src/database/engineReads.ts +0 -304
- package/src/database/engineTransaction.spec.ts +0 -710
- package/src/database/engineTransaction.ts +0 -582
- package/src/database/errors.ts +0 -30
- package/src/database/fence.spec.ts +0 -223
- package/src/database/fence.ts +0 -175
- package/src/database/index.ts +0 -160
- package/src/database/kv/kvAdapter.batching.integration.spec.ts +0 -15
- package/src/database/kv/kvAdapter.conformance.integration.spec.ts +0 -19
- package/src/database/kv/kvAdapter.readBudgets.integration.spec.ts +0 -17
- package/src/database/kv/kvAdapter.spec.ts +0 -595
- package/src/database/kv/kvAdapter.ts +0 -479
- package/src/database/kv/kvTestStore.ts +0 -118
- package/src/database/memory.readBudgets.integration.spec.ts +0 -13
- package/src/database/resolveSchema.spec.ts +0 -230
- package/src/database/resolveSchema.ts +0 -375
- package/src/database/retention.spec.ts +0 -314
- package/src/database/retention.ts +0 -129
- package/src/database/schema.ts +0 -213
- package/src/database/schema.types.spec.ts +0 -94
- package/src/database/sql/docker-compose.yml +0 -36
- package/src/database/sql/sqlAdapter.integration.spec.ts +0 -145
- package/src/database/sql/sqlAdapter.readBudgets.integration.spec.ts +0 -123
- package/src/database/sql/sqlAdapter.spec.ts +0 -343
- package/src/database/sql/sqlAdapter.ts +0 -552
- package/src/database/sql/sqlSchema.ts +0 -286
- package/src/database/sql/sqlTestExecutors.ts +0 -183
- package/src/databaseTestSuite.spec.ts +0 -44
- package/src/db/bundleRows.spec.ts +0 -164
- package/src/db/bundleRows.ts +0 -10
- package/src/db/coreDatabase.ts +0 -153
- package/src/db/createBundleDiff.spec.ts +0 -464
- package/src/db/createBundleDiff.ts +0 -370
- package/src/db/engineDrizzleSchema.ts +0 -72
- package/src/db/engineMigrator.ts +0 -105
- package/src/db/enginePrismaSchema.ts +0 -147
- package/src/db/engineSql.spec.ts +0 -130
- package/src/db/engineSql.ts +0 -48
- package/src/db/engineSqlMigrator.ts +0 -116
- package/src/db/fixedMigratorShared.ts +0 -17
- package/src/db/index.spec.ts +0 -554
- package/src/db/index.ts +0 -93
- package/src/db/node-sqlite.d.ts +0 -25
- package/src/db/pluginTables.spec.ts +0 -248
- package/src/db/releaseCatalog.ts +0 -106
- package/src/db/schemaSettings.ts +0 -104
- package/src/db/settingsMigrator.spec.ts +0 -65
- package/src/db/settingsMigrator.ts +0 -152
- package/src/db/types.ts +0 -82
- package/src/db/updateArtifacts.spec.ts +0 -235
- package/src/db/updateArtifacts.ts +0 -473
- package/src/db/updateCheck.bench.ts +0 -47
- package/src/diff.ts +0 -6
- package/src/handler-standalone.integration.spec.ts +0 -321
- package/src/handler.spec.ts +0 -273
- package/src/handler.testFixtures.ts +0 -25
- package/src/handler.ts +0 -302
- package/src/handlerAdminRoutes.spec.ts +0 -183
- package/src/handlerAdminRoutes.ts +0 -536
- package/src/handlerAuth.integration.spec.ts +0 -33
- package/src/handlerErrors.ts +0 -7
- package/src/handlerManagement.spec.ts +0 -202
- package/src/handlerParameters.ts +0 -105
- package/src/handlerReleaseCatalogRoutes.ts +0 -176
- package/src/handlerTypes.ts +0 -19
- package/src/handlerVersionRoutes.ts +0 -25
- package/src/index.ts +0 -13
- package/src/internalRouter.ts +0 -104
- package/src/lintRules.spec.ts +0 -76
- package/src/node.spec.ts +0 -119
- package/src/node.ts +0 -111
- package/src/plugins/api-keys/apiKeys.integration.spec.ts +0 -92
- package/src/plugins/api-keys/apiKeys.spec.ts +0 -166
- package/src/plugins/api-keys/apiKeys.ts +0 -214
- package/src/plugins/api-keys/apiKeysPlugin.spec.ts +0 -168
- package/src/plugins/api-keys/cli.spec.ts +0 -187
- package/src/plugins/api-keys/cli.ts +0 -140
- package/src/plugins/api-keys/index.ts +0 -73
- package/src/plugins/api-keys/model.ts +0 -88
- package/src/plugins/api-keys/schema.ts +0 -22
- package/src/plugins/definePlugin.ts +0 -242
- package/src/plugins/index.ts +0 -73
- package/src/plugins/insights/contract.spec.ts +0 -285
- package/src/plugins/insights/contract.ts +0 -372
- package/src/plugins/insights/domain.ts +0 -176
- package/src/plugins/insights/errors.ts +0 -11
- package/src/plugins/insights/eventInput.ts +0 -381
- package/src/plugins/insights/eventRow.ts +0 -209
- package/src/plugins/insights/index.ts +0 -222
- package/src/plugins/insights/insights.integration.spec.ts +0 -921
- package/src/plugins/insights/insightsRollout.integration.spec.ts +0 -186
- package/src/plugins/insights/model.spec.ts +0 -64
- package/src/plugins/insights/model.ts +0 -18
- package/src/plugins/insights/modelTypes.ts +0 -197
- package/src/plugins/insights/overview.spec.ts +0 -64
- package/src/plugins/insights/overview.ts +0 -214
- package/src/plugins/insights/provider.spec.ts +0 -585
- package/src/plugins/insights/provider.ts +0 -704
- package/src/plugins/insights/queryInput.ts +0 -142
- package/src/plugins/insights/reads.spec.ts +0 -1013
- package/src/plugins/insights/reads.ts +0 -1037
- package/src/plugins/insights/recordEvent.spec.ts +0 -897
- package/src/plugins/insights/recordEvent.ts +0 -476
- package/src/plugins/insights/retention.spec.ts +0 -115
- package/src/plugins/insights/routes.ts +0 -149
- package/src/plugins/insights/schema.ts +0 -409
- package/src/plugins/insights/testing/expectInsightsIndex.spec.ts +0 -42
- package/src/plugins/insights/testing/expectInsightsIndex.ts +0 -20
- package/src/plugins/insights/testing/fixtures.ts +0 -30
- package/src/plugins/insights/testing/index.ts +0 -45
- package/src/plugins/insights/testing/insightsModelTests.ts +0 -860
- package/src/plugins/insights/testing/setupInsightsHttpTestSuite.ts +0 -152
- package/src/plugins/insights/testing/setupInsightsModelTestSuite.ts +0 -36
- package/src/plugins/insights/testing/types.ts +0 -30
- package/src/plugins/insights/types.ts +0 -55
- package/src/plugins/pluginTestHarness.spec.ts +0 -56
- package/src/readBudgets.testFixtures.ts +0 -15
- package/src/releaseCatalogRoutes.integration.spec.ts +0 -200
- package/src/retention.spec.ts +0 -73
- package/src/runtime.spec.ts +0 -207
- package/src/runtime.testFixtures.ts +0 -60
- package/src/runtimeBundles.integration.spec.ts +0 -112
- package/src/storageAccess.spec.ts +0 -152
- package/src/storageAccess.ts +0 -141
- package/src/testUtilsMutation.integration.spec.ts +0 -216
- package/src/testUtilsPackage.integration.spec.ts +0 -180
- package/src/types/index.ts +0 -2
- package/src/version.ts +0 -3
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import type { Deployment } from "@hot-updater/plugin-core";
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
-
|
|
4
|
-
import { createHotUpdaterHandlers } from "./handler";
|
|
5
|
-
import {
|
|
6
|
-
createAdminHandler,
|
|
7
|
-
createApi,
|
|
8
|
-
testBundle,
|
|
9
|
-
} from "./handler.testFixtures";
|
|
10
|
-
|
|
11
|
-
const BASE = "http://localhost";
|
|
12
|
-
|
|
13
|
-
const send = (method: string, path: string, body?: unknown) =>
|
|
14
|
-
new Request(`${BASE}${path}`, {
|
|
15
|
-
method,
|
|
16
|
-
...(body === undefined
|
|
17
|
-
? {}
|
|
18
|
-
: {
|
|
19
|
-
body: JSON.stringify(body),
|
|
20
|
-
headers: { "content-type": "application/json" },
|
|
21
|
-
}),
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const deployment = (id: string, channel = "production"): Deployment => ({
|
|
25
|
-
bundle: { ...testBundle, id },
|
|
26
|
-
release: {
|
|
27
|
-
channel,
|
|
28
|
-
enabled: false,
|
|
29
|
-
fingerprintHash: null,
|
|
30
|
-
message: null,
|
|
31
|
-
shouldForceUpdate: false,
|
|
32
|
-
targetAppVersion: "1.0.x",
|
|
33
|
-
},
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const BUNDLE_A = "01900000-0000-7000-8000-000000000001";
|
|
37
|
-
const BUNDLE_B = "01900000-0000-7000-8000-000000000002";
|
|
38
|
-
|
|
39
|
-
describe("admin routes on core", () => {
|
|
40
|
-
it("does not match client routes", async () => {
|
|
41
|
-
const handler = createAdminHandler();
|
|
42
|
-
const response = await handler(
|
|
43
|
-
send("GET", `/artifacts/v1/${BUNDLE_B}/from/${BUNDLE_A}`),
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
expect(response.status).toBe(404);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it("reports the admin API protocol where standalone clients call", async () => {
|
|
50
|
-
const handler = createAdminHandler();
|
|
51
|
-
const response = await handler(send("GET", "/version"));
|
|
52
|
-
|
|
53
|
-
expect(response.status).toBe(200);
|
|
54
|
-
expect(response.headers.get("cache-control")).toBe("private, no-store");
|
|
55
|
-
await expect(response.json()).resolves.toMatchObject({
|
|
56
|
-
adminProtocol: 2,
|
|
57
|
-
plugins: [],
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it("lists the plugins the server runs, sorted, for a console", async () => {
|
|
62
|
-
const handler = createHotUpdaterHandlers({
|
|
63
|
-
api: createApi(),
|
|
64
|
-
plugins: ["insights", "apiKeys"],
|
|
65
|
-
}).admin;
|
|
66
|
-
|
|
67
|
-
const response = await handler(send("GET", "/version"));
|
|
68
|
-
|
|
69
|
-
await expect(response.json()).resolves.toMatchObject({
|
|
70
|
-
adminProtocol: 2,
|
|
71
|
-
plugins: ["apiKeys", "insights"],
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it.each([
|
|
76
|
-
["POST", "/database/commit"],
|
|
77
|
-
["POST", "/bundles"],
|
|
78
|
-
["DELETE", `/bundles/${BUNDLE_A}`],
|
|
79
|
-
])("no longer serves protocol 1's %s %s", async (method, path) => {
|
|
80
|
-
const handler = createAdminHandler();
|
|
81
|
-
|
|
82
|
-
const response = await handler(send(method, path, {}));
|
|
83
|
-
|
|
84
|
-
expect(response.status).toBe(404);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it("creates, finds, lists, and deletes a channel, with or without v=2", async () => {
|
|
88
|
-
const handler = createAdminHandler();
|
|
89
|
-
|
|
90
|
-
const created = await handler(
|
|
91
|
-
send("POST", "/channels", { name: "preview" }),
|
|
92
|
-
);
|
|
93
|
-
const again = await handler(
|
|
94
|
-
send("POST", "/channels?v=2", { name: "preview" }),
|
|
95
|
-
);
|
|
96
|
-
const { data: channel } = (await created.json()) as {
|
|
97
|
-
data: { id: string; name: string };
|
|
98
|
-
};
|
|
99
|
-
const found = await handler(send("GET", "/channels?name=preview"));
|
|
100
|
-
const listed = await handler(send("GET", "/channels?v=2"));
|
|
101
|
-
|
|
102
|
-
expect(created.status).toBe(200);
|
|
103
|
-
expect(channel.name).toBe("preview");
|
|
104
|
-
await expect(again.json()).resolves.toEqual({ data: channel });
|
|
105
|
-
await expect(found.json()).resolves.toEqual({ data: channel });
|
|
106
|
-
await expect(listed.json()).resolves.toEqual({ data: [channel] });
|
|
107
|
-
|
|
108
|
-
const deleted = await handler(send("DELETE", `/channels/${channel.id}`));
|
|
109
|
-
const missing = await handler(send("DELETE", `/channels/${channel.id}`));
|
|
110
|
-
|
|
111
|
-
expect(deleted.status).toBe(204);
|
|
112
|
-
await expect(deleted.text()).resolves.toBe("");
|
|
113
|
-
expect(missing.status).toBe(404);
|
|
114
|
-
await expect(missing.json()).resolves.toEqual({
|
|
115
|
-
data: { deleted: false, reason: "not_found" },
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it("refuses to delete a channel a release uses", async () => {
|
|
120
|
-
const api = createApi();
|
|
121
|
-
await api.core.deploy([deployment(BUNDLE_A)]);
|
|
122
|
-
const channel = await api.core.findChannelByName("production");
|
|
123
|
-
const handler = createAdminHandler(api);
|
|
124
|
-
|
|
125
|
-
const response = await handler(send("DELETE", `/channels/${channel!.id}`));
|
|
126
|
-
|
|
127
|
-
expect(response.status).toBe(409);
|
|
128
|
-
await expect(response.json()).resolves.toEqual({
|
|
129
|
-
data: { deleted: false, reason: "not_empty" },
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it("pages bundles by key, newest first", async () => {
|
|
134
|
-
const api = createApi();
|
|
135
|
-
await api.core.deploy([deployment(BUNDLE_A)]);
|
|
136
|
-
await api.core.deploy([deployment(BUNDLE_B)]);
|
|
137
|
-
const handler = createAdminHandler(api);
|
|
138
|
-
|
|
139
|
-
const first = await handler(send("GET", "/bundles?limit=1&total=true"));
|
|
140
|
-
const firstPage = (await first.json()) as {
|
|
141
|
-
data: { bundle: { id: string } }[];
|
|
142
|
-
next: string;
|
|
143
|
-
total: number;
|
|
144
|
-
};
|
|
145
|
-
const second = await handler(
|
|
146
|
-
send("GET", `/bundles?limit=1&cursor=${firstPage.next}`),
|
|
147
|
-
);
|
|
148
|
-
const secondPage = (await second.json()) as {
|
|
149
|
-
data: { bundle: { id: string } }[];
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
expect(firstPage.data.map(({ bundle }) => bundle.id)).toEqual([BUNDLE_B]);
|
|
153
|
-
expect(firstPage.total).toBe(2);
|
|
154
|
-
expect(secondPage.data.map(({ bundle }) => bundle.id)).toEqual([BUNDLE_A]);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it.each(["limit=101", "order=random", "platform=web"])(
|
|
158
|
-
"refuses the bundle list query %s",
|
|
159
|
-
async (query) => {
|
|
160
|
-
const handler = createAdminHandler();
|
|
161
|
-
|
|
162
|
-
const response = await handler(send("GET", `/bundles?${query}`));
|
|
163
|
-
|
|
164
|
-
expect(response.status).toBe(400);
|
|
165
|
-
},
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
it("changes a bundle's fields and refuses another bundle's id", async () => {
|
|
169
|
-
const api = createApi();
|
|
170
|
-
await api.core.deploy([deployment(BUNDLE_A)]);
|
|
171
|
-
const handler = createAdminHandler(api);
|
|
172
|
-
|
|
173
|
-
const updated = await handler(
|
|
174
|
-
send("PATCH", `/bundles/${BUNDLE_A}`, { gitCommitHash: "abc123" }),
|
|
175
|
-
);
|
|
176
|
-
const mismatch = await handler(
|
|
177
|
-
send("PATCH", `/bundles/${BUNDLE_A}`, { id: BUNDLE_B }),
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
expect(updated.status).toBe(204);
|
|
181
|
-
expect((await api.core.getBundle(BUNDLE_A))?.bundle.git_commit_hash).toBe(
|
|
182
|
-
"abc123",
|
|
183
|
-
);
|
|
184
|
-
expect(mismatch.status).toBe(400);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it("hard-deletes a disabled release only when confirm names it", async () => {
|
|
188
|
-
const api = createApi();
|
|
189
|
-
const [result] = await api.core.deploy([deployment(BUNDLE_A)]);
|
|
190
|
-
const releaseId = result!.release!.id;
|
|
191
|
-
const handler = createAdminHandler(api);
|
|
192
|
-
|
|
193
|
-
const unconfirmed = await handler(send("DELETE", `/releases/${releaseId}`));
|
|
194
|
-
const deleted = await handler(
|
|
195
|
-
send("DELETE", `/releases/${releaseId}?confirm=${releaseId}`),
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
expect(unconfirmed.status).toBe(400);
|
|
199
|
-
expect(deleted.status).toBe(200);
|
|
200
|
-
await expect(api.core.getRelease(releaseId)).resolves.toBeNull();
|
|
201
|
-
});
|
|
202
|
-
});
|
package/src/handlerParameters.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import type { Platform } from "@hot-updater/core";
|
|
2
|
-
|
|
3
|
-
import { HandlerBadRequestError } from "./handlerErrors";
|
|
4
|
-
|
|
5
|
-
type PositiveIntegerBounds = {
|
|
6
|
-
readonly defaultValue: number;
|
|
7
|
-
readonly maxValue: number;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const decodeMaybe = (value: string | undefined): string | undefined => {
|
|
11
|
-
if (value === undefined) return undefined;
|
|
12
|
-
try {
|
|
13
|
-
return decodeURIComponent(value);
|
|
14
|
-
} catch {
|
|
15
|
-
return value;
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const isPlatform = (value: string): value is Platform =>
|
|
20
|
-
value === "ios" || value === "android";
|
|
21
|
-
|
|
22
|
-
export const requireRouteParam = (
|
|
23
|
-
params: Record<string, string>,
|
|
24
|
-
key: string,
|
|
25
|
-
): string => {
|
|
26
|
-
const value = params[key];
|
|
27
|
-
if (!value) {
|
|
28
|
-
throw new HandlerBadRequestError(`Missing route parameter: ${key}`);
|
|
29
|
-
}
|
|
30
|
-
return value;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export const requirePlatformParam = (
|
|
34
|
-
params: Record<string, string>,
|
|
35
|
-
): Platform => {
|
|
36
|
-
const platform = requireRouteParam(params, "platform");
|
|
37
|
-
if (!isPlatform(platform)) {
|
|
38
|
-
throw new HandlerBadRequestError(
|
|
39
|
-
`Invalid platform: ${platform}. Expected 'ios' or 'android'.`,
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
return platform;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const parseBooleanSearchParam = (
|
|
46
|
-
url: URL,
|
|
47
|
-
key: string,
|
|
48
|
-
): boolean | undefined => {
|
|
49
|
-
const value = url.searchParams.get(key);
|
|
50
|
-
if (value === null) return undefined;
|
|
51
|
-
if (value === "true") return true;
|
|
52
|
-
if (value === "false") return false;
|
|
53
|
-
throw new HandlerBadRequestError(
|
|
54
|
-
`The '${key}' query parameter must be 'true' or 'false'.`,
|
|
55
|
-
);
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export const parseNullableStringSearchParam = (
|
|
59
|
-
url: URL,
|
|
60
|
-
key: string,
|
|
61
|
-
): string | null | undefined => {
|
|
62
|
-
const value = url.searchParams.get(key);
|
|
63
|
-
if (value === null) return undefined;
|
|
64
|
-
return value === "null" ? null : value;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export const parseStringArraySearchParam = (
|
|
68
|
-
url: URL,
|
|
69
|
-
key: string,
|
|
70
|
-
): string[] | undefined => {
|
|
71
|
-
const values = url.searchParams.getAll(key);
|
|
72
|
-
return values.length > 0 ? values : undefined;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
export const parsePositiveIntegerSearchParam = (
|
|
76
|
-
url: URL,
|
|
77
|
-
key: string,
|
|
78
|
-
bounds: PositiveIntegerBounds,
|
|
79
|
-
): number => {
|
|
80
|
-
const value = url.searchParams.get(key);
|
|
81
|
-
if (value === null) return bounds.defaultValue;
|
|
82
|
-
const parsed = Number(value);
|
|
83
|
-
if (!Number.isInteger(parsed) || parsed < 1 || parsed > bounds.maxValue) {
|
|
84
|
-
throw new HandlerBadRequestError(
|
|
85
|
-
`The '${key}' query parameter must be a positive integer between 1 and ${bounds.maxValue}.`,
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
return parsed;
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
export const parseNonNegativeIntegerSearchParam = (
|
|
92
|
-
url: URL,
|
|
93
|
-
key: string,
|
|
94
|
-
defaultValue: number,
|
|
95
|
-
): number => {
|
|
96
|
-
const value = url.searchParams.get(key);
|
|
97
|
-
if (value === null) return defaultValue;
|
|
98
|
-
const parsed = Number(value);
|
|
99
|
-
if (!Number.isSafeInteger(parsed) || parsed < 0) {
|
|
100
|
-
throw new HandlerBadRequestError(
|
|
101
|
-
`The '${key}' query parameter must be a non-negative integer.`,
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
return parsed;
|
|
105
|
-
};
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import type { ReleaseCatalog } from "@hot-updater/core";
|
|
2
|
-
import { canonicalizeAppVersion } from "@hot-updater/plugin-core";
|
|
3
|
-
|
|
4
|
-
import { requirePlatformParam, requireRouteParam } from "./handlerParameters";
|
|
5
|
-
import type { RouteHandler } from "./handlerTypes";
|
|
6
|
-
|
|
7
|
-
const CATALOG_CONTENT_TYPE =
|
|
8
|
-
"application/vnd.hot-updater.release-catalog+json; version=1";
|
|
9
|
-
const ARTIFACT_CONTENT_TYPE =
|
|
10
|
-
"application/vnd.hot-updater.artifact+json; version=1";
|
|
11
|
-
const ORIGIN_CACHE_TTL_MS = 5_000;
|
|
12
|
-
const ORIGIN_CACHE_MAX_ENTRIES = 128;
|
|
13
|
-
/** Marks the 404 of a scope that has no catalog. */
|
|
14
|
-
const NO_CATALOG_HEADER = "x-hot-updater-catalog";
|
|
15
|
-
/** A shared cache keeps a catalog, or a scope's lack of one, five seconds. */
|
|
16
|
-
const CATALOG_CACHE_CONTROL = "public, max-age=0, s-maxage=5";
|
|
17
|
-
|
|
18
|
-
const privateNotFound = (): Response =>
|
|
19
|
-
Response.json(
|
|
20
|
-
{ error: "Not found" },
|
|
21
|
-
{
|
|
22
|
-
status: 404,
|
|
23
|
-
headers: { "cache-control": "private, no-store" },
|
|
24
|
-
},
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* A scope with no catalog yet, such as a store version before its first
|
|
29
|
-
* OTA release: cached like a catalog, so its update checks don't all reach
|
|
30
|
-
* the origin, and it holds nothing an API key protects. The header tells it
|
|
31
|
-
* apart from a 404 for a wrong URL: clients read it as "no update", and
|
|
32
|
-
* doctor as a live catalog route.
|
|
33
|
-
*/
|
|
34
|
-
const missingCatalog = (): Response =>
|
|
35
|
-
Response.json(
|
|
36
|
-
{ error: "Not found" },
|
|
37
|
-
{
|
|
38
|
-
status: 404,
|
|
39
|
-
headers: {
|
|
40
|
-
"cache-control": CATALOG_CACHE_CONTROL,
|
|
41
|
-
vary: "Accept-Encoding",
|
|
42
|
-
[NO_CATALOG_HEADER]: "none",
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
const responseHash = async (body: string): Promise<string> => {
|
|
48
|
-
const digest = await crypto.subtle.digest(
|
|
49
|
-
"SHA-256",
|
|
50
|
-
new TextEncoder().encode(body),
|
|
51
|
-
);
|
|
52
|
-
return [...new Uint8Array(digest)]
|
|
53
|
-
.map((byte) => byte.toString(16).padStart(2, "0"))
|
|
54
|
-
.join("");
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const catalogResponse = async (
|
|
58
|
-
catalog: ReleaseCatalog | null,
|
|
59
|
-
request: Request,
|
|
60
|
-
): Promise<Response> => {
|
|
61
|
-
if (catalog === null) return missingCatalog();
|
|
62
|
-
const body = JSON.stringify(catalog);
|
|
63
|
-
const etag = `"sha256:${await responseHash(body)}"`;
|
|
64
|
-
const headers = {
|
|
65
|
-
"cache-control": CATALOG_CACHE_CONTROL,
|
|
66
|
-
"content-type": CATALOG_CONTENT_TYPE,
|
|
67
|
-
etag,
|
|
68
|
-
vary: "Accept-Encoding",
|
|
69
|
-
};
|
|
70
|
-
if (request.headers.get("if-none-match") === etag) {
|
|
71
|
-
return new Response(null, { headers, status: 304 });
|
|
72
|
-
}
|
|
73
|
-
return new Response(body, { headers, status: 200 });
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export const createReleaseCatalogRouteHandlers = (): Record<
|
|
77
|
-
string,
|
|
78
|
-
RouteHandler
|
|
79
|
-
> => {
|
|
80
|
-
const cache = new Map<
|
|
81
|
-
string,
|
|
82
|
-
{ readonly catalog: ReleaseCatalog; readonly expiresAt: number }
|
|
83
|
-
>();
|
|
84
|
-
const inFlight = new Map<string, Promise<ReleaseCatalog | null>>();
|
|
85
|
-
const loadCatalog = async (
|
|
86
|
-
key: string,
|
|
87
|
-
load: () => Promise<ReleaseCatalog | null>,
|
|
88
|
-
): Promise<ReleaseCatalog | null> => {
|
|
89
|
-
const cached = cache.get(key);
|
|
90
|
-
if (cached !== undefined && cached.expiresAt > Date.now()) {
|
|
91
|
-
cache.delete(key);
|
|
92
|
-
cache.set(key, cached);
|
|
93
|
-
return cached.catalog;
|
|
94
|
-
}
|
|
95
|
-
if (cached !== undefined) cache.delete(key);
|
|
96
|
-
const pending = inFlight.get(key);
|
|
97
|
-
if (pending !== undefined) return pending;
|
|
98
|
-
|
|
99
|
-
const next = load().then((catalog) => {
|
|
100
|
-
if (catalog !== null) {
|
|
101
|
-
cache.set(key, {
|
|
102
|
-
catalog,
|
|
103
|
-
expiresAt: Date.now() + ORIGIN_CACHE_TTL_MS,
|
|
104
|
-
});
|
|
105
|
-
while (cache.size > ORIGIN_CACHE_MAX_ENTRIES) {
|
|
106
|
-
const oldestKey = cache.keys().next().value as string | undefined;
|
|
107
|
-
if (oldestKey === undefined) break;
|
|
108
|
-
cache.delete(oldestKey);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return catalog;
|
|
112
|
-
});
|
|
113
|
-
inFlight.set(key, next);
|
|
114
|
-
try {
|
|
115
|
-
return await next;
|
|
116
|
-
} finally {
|
|
117
|
-
inFlight.delete(key);
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
appVersionReleaseCatalog: async (params, request, { core }) => {
|
|
123
|
-
const rawAppVersion = requireRouteParam(params, "appVersion");
|
|
124
|
-
const appVersion = canonicalizeAppVersion(rawAppVersion);
|
|
125
|
-
if (appVersion === null || appVersion !== rawAppVersion) {
|
|
126
|
-
return Response.json(
|
|
127
|
-
{ error: "Invalid app version" },
|
|
128
|
-
{ status: 400, headers: { "cache-control": "private, no-store" } },
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
const input = {
|
|
132
|
-
appVersion,
|
|
133
|
-
channelKey: requireRouteParam(params, "channelKey"),
|
|
134
|
-
platform: requirePlatformParam(params),
|
|
135
|
-
strategy: "APP_VERSION",
|
|
136
|
-
} as const;
|
|
137
|
-
return catalogResponse(
|
|
138
|
-
await loadCatalog(`app-version:${JSON.stringify(input)}`, () =>
|
|
139
|
-
core.getReleaseCatalog(input),
|
|
140
|
-
),
|
|
141
|
-
request,
|
|
142
|
-
);
|
|
143
|
-
},
|
|
144
|
-
|
|
145
|
-
fingerprintReleaseCatalog: async (params, request, { core }) => {
|
|
146
|
-
const input = {
|
|
147
|
-
channelKey: requireRouteParam(params, "channelKey"),
|
|
148
|
-
fingerprintHash: requireRouteParam(params, "fingerprintHash"),
|
|
149
|
-
platform: requirePlatformParam(params),
|
|
150
|
-
strategy: "FINGERPRINT",
|
|
151
|
-
} as const;
|
|
152
|
-
return catalogResponse(
|
|
153
|
-
await loadCatalog(`fingerprint:${JSON.stringify(input)}`, () =>
|
|
154
|
-
core.getReleaseCatalog(input),
|
|
155
|
-
),
|
|
156
|
-
request,
|
|
157
|
-
);
|
|
158
|
-
},
|
|
159
|
-
|
|
160
|
-
artifactV1: async (params, _request, { core }) => {
|
|
161
|
-
const info = await core.getArtifactInfo(
|
|
162
|
-
requireRouteParam(params, "targetBundleId"),
|
|
163
|
-
requireRouteParam(params, "currentBundleId"),
|
|
164
|
-
1,
|
|
165
|
-
);
|
|
166
|
-
if (info === null) return privateNotFound();
|
|
167
|
-
return new Response(JSON.stringify(info), {
|
|
168
|
-
status: 200,
|
|
169
|
-
headers: {
|
|
170
|
-
"cache-control": "private, no-store",
|
|
171
|
-
"content-type": ARTIFACT_CONTENT_TYPE,
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
},
|
|
175
|
-
};
|
|
176
|
-
};
|
package/src/handlerTypes.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { CoreApi } from "./core/api";
|
|
2
|
-
|
|
3
|
-
/** What the handlers run on: core's reads and typed writes. */
|
|
4
|
-
export interface HandlerAPI {
|
|
5
|
-
readonly core: CoreApi;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export type HotUpdaterHandler = (request: Request) => Promise<Response>;
|
|
9
|
-
|
|
10
|
-
export interface HotUpdaterHandlers {
|
|
11
|
-
readonly client: HotUpdaterHandler;
|
|
12
|
-
readonly admin: HotUpdaterHandler;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export type RouteHandler = (
|
|
16
|
-
params: Record<string, string>,
|
|
17
|
-
request: Request,
|
|
18
|
-
api: HandlerAPI,
|
|
19
|
-
) => Promise<Response>;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { ADMIN_API_PROTOCOL } from "./handlerAdminRoutes";
|
|
2
|
-
import type { RouteHandler } from "./handlerTypes";
|
|
3
|
-
import { HOT_UPDATER_SERVER_VERSION } from "./version";
|
|
4
|
-
|
|
5
|
-
export const HOT_UPDATER_INFRASTRUCTURE_GENERATION = 1;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* `/version` on both mounts. The admin mount also lists the ids of the
|
|
9
|
-
* plugins the server runs, sorted, so a console shows only the features they
|
|
10
|
-
* serve; apps never learn which plugins a server runs.
|
|
11
|
-
*/
|
|
12
|
-
export const createVersionRouteHandlers = (
|
|
13
|
-
plugins: readonly string[] = [],
|
|
14
|
-
): Record<string, RouteHandler> => {
|
|
15
|
-
const version = {
|
|
16
|
-
adminProtocol: ADMIN_API_PROTOCOL,
|
|
17
|
-
infrastructureGeneration: HOT_UPDATER_INFRASTRUCTURE_GENERATION,
|
|
18
|
-
version: HOT_UPDATER_SERVER_VERSION,
|
|
19
|
-
};
|
|
20
|
-
const adminVersion = { ...version, plugins: [...plugins].sort() };
|
|
21
|
-
return {
|
|
22
|
-
version: async () => Response.json(version),
|
|
23
|
-
adminVersion: async () => Response.json(adminVersion),
|
|
24
|
-
};
|
|
25
|
-
};
|
package/src/index.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export type { HotUpdaterHandler, HotUpdaterHandlers } from "./handler";
|
|
2
|
-
export { createHotUpdater } from "./createHotUpdaterCore";
|
|
3
|
-
export type {
|
|
4
|
-
ClientAccessPolicy,
|
|
5
|
-
ClientAccessRule,
|
|
6
|
-
CreateHotUpdaterOptions,
|
|
7
|
-
HotUpdaterAPI,
|
|
8
|
-
RuntimeHotUpdaterAPI,
|
|
9
|
-
} from "./createHotUpdaterCore";
|
|
10
|
-
export { HotUpdaterConfigError } from "./assembly/assemblePlugins";
|
|
11
|
-
export * from "./types";
|
|
12
|
-
export { HOT_UPDATER_SERVER_VERSION } from "./version";
|
|
13
|
-
export { HOT_UPDATER_INFRASTRUCTURE_GENERATION } from "./handlerVersionRoutes";
|
package/src/internalRouter.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
interface RouteRecord<T> {
|
|
2
|
-
data: T;
|
|
3
|
-
method: string;
|
|
4
|
-
paramNames: string[];
|
|
5
|
-
segments: string[];
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
interface RouteMatch<T> {
|
|
9
|
-
data: T;
|
|
10
|
-
params: Record<string, string>;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface Router<T> {
|
|
14
|
-
routes: RouteRecord<T>[];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const normalizePath = (path: string) => {
|
|
18
|
-
if (!path) {
|
|
19
|
-
return "/";
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (path === "/") {
|
|
23
|
-
return path;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const withLeadingSlash = path.startsWith("/") ? path : `/${path}`;
|
|
27
|
-
return withLeadingSlash.endsWith("/")
|
|
28
|
-
? withLeadingSlash.slice(0, -1)
|
|
29
|
-
: withLeadingSlash;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const toSegments = (path: string) => {
|
|
33
|
-
const normalized = normalizePath(path);
|
|
34
|
-
return normalized === "/" ? [] : normalized.slice(1).split("/");
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export function createRouter<T>(): Router<T> {
|
|
38
|
-
return { routes: [] };
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function addRoute<T>(
|
|
42
|
-
router: Router<T>,
|
|
43
|
-
method: string,
|
|
44
|
-
path: string,
|
|
45
|
-
data: T,
|
|
46
|
-
) {
|
|
47
|
-
const segments = toSegments(path);
|
|
48
|
-
const paramNames = segments
|
|
49
|
-
.filter((segment) => segment.startsWith(":"))
|
|
50
|
-
.map((segment) => segment.slice(1));
|
|
51
|
-
|
|
52
|
-
router.routes.push({
|
|
53
|
-
data,
|
|
54
|
-
method: method.toUpperCase(),
|
|
55
|
-
paramNames,
|
|
56
|
-
segments,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function findRoute<T>(
|
|
61
|
-
router: Router<T>,
|
|
62
|
-
method: string,
|
|
63
|
-
path: string,
|
|
64
|
-
): RouteMatch<T> | undefined {
|
|
65
|
-
const normalizedMethod = method.toUpperCase();
|
|
66
|
-
const pathSegments = toSegments(path);
|
|
67
|
-
|
|
68
|
-
for (const route of router.routes) {
|
|
69
|
-
if (route.method !== normalizedMethod) {
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (route.segments.length !== pathSegments.length) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const params: Record<string, string> = {};
|
|
78
|
-
let matched = true;
|
|
79
|
-
|
|
80
|
-
for (let index = 0; index < route.segments.length; index += 1) {
|
|
81
|
-
const routeSegment = route.segments[index];
|
|
82
|
-
const pathSegment = pathSegments[index];
|
|
83
|
-
|
|
84
|
-
if (routeSegment.startsWith(":")) {
|
|
85
|
-
params[routeSegment.slice(1)] = pathSegment;
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (routeSegment !== pathSegment) {
|
|
90
|
-
matched = false;
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (matched) {
|
|
96
|
-
return {
|
|
97
|
-
data: route.data,
|
|
98
|
-
params,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return undefined;
|
|
104
|
-
}
|