@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,284 +0,0 @@
|
|
|
1
|
-
const require_errors = require("./errors.cjs");
|
|
2
|
-
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
3
|
-
//#region src/plugins/insights/eventInput.ts
|
|
4
|
-
const MAX_EVENT_STRING_LENGTH = 1024;
|
|
5
|
-
const MAX_IDENTITY_LENGTH = 255;
|
|
6
|
-
const EVENT_BODY_MAX_BYTES = 16384;
|
|
7
|
-
function isRecord(value) {
|
|
8
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
|
-
}
|
|
10
|
-
function requireStringField(payload, key) {
|
|
11
|
-
const value = payload[key];
|
|
12
|
-
if (typeof value !== "string" || value.length === 0 || value.length > MAX_EVENT_STRING_LENGTH || new TextDecoder("utf-8", { ignoreBOM: true }).decode(new TextEncoder().encode(value)) !== value) throw new require_errors.InsightsBadRequestError(`Invalid event field: ${key}`);
|
|
13
|
-
return value;
|
|
14
|
-
}
|
|
15
|
-
function requireNullableStringField(payload, key) {
|
|
16
|
-
if (payload[key] === null) return null;
|
|
17
|
-
return requireStringField(payload, key);
|
|
18
|
-
}
|
|
19
|
-
function requireIdentityField(payload, key) {
|
|
20
|
-
const value = requireStringField(payload, key);
|
|
21
|
-
if (value.length > MAX_IDENTITY_LENGTH) throw new require_errors.InsightsBadRequestError(`Invalid event field: ${key}`);
|
|
22
|
-
return value;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* The report's idempotency key, when the client sends one: it creates the
|
|
26
|
-
* UUIDv7 once and repeats it on every retry of that report.
|
|
27
|
-
*/
|
|
28
|
-
function readEventId(payload) {
|
|
29
|
-
const value = payload.eventId;
|
|
30
|
-
if (value === void 0) return void 0;
|
|
31
|
-
if (!(0, _hot_updater_plugin_core.isUUIDv7)(value)) throw new require_errors.InsightsBadRequestError("Invalid event field: eventId");
|
|
32
|
-
return value;
|
|
33
|
-
}
|
|
34
|
-
/** One value of an open set: any other value reads as `unknown`. */
|
|
35
|
-
const oneOf = (values, value) => values.includes(value) ? value : "unknown";
|
|
36
|
-
const STAGES = [
|
|
37
|
-
"check",
|
|
38
|
-
"download",
|
|
39
|
-
"install"
|
|
40
|
-
];
|
|
41
|
-
const REASONS = [
|
|
42
|
-
"network",
|
|
43
|
-
"http",
|
|
44
|
-
"invalid_response",
|
|
45
|
-
"hash_mismatch",
|
|
46
|
-
"signature",
|
|
47
|
-
"patch",
|
|
48
|
-
"extract",
|
|
49
|
-
"storage"
|
|
50
|
-
];
|
|
51
|
-
const RESOURCES = [
|
|
52
|
-
"catalog",
|
|
53
|
-
"artifact",
|
|
54
|
-
"manifest",
|
|
55
|
-
"file",
|
|
56
|
-
"patch",
|
|
57
|
-
"archive"
|
|
58
|
-
];
|
|
59
|
-
const TRANSPORTS = [
|
|
60
|
-
"timeout",
|
|
61
|
-
"dns",
|
|
62
|
-
"tls",
|
|
63
|
-
"connection",
|
|
64
|
-
"offline",
|
|
65
|
-
"cancelled"
|
|
66
|
-
];
|
|
67
|
-
const DELIVERIES = [
|
|
68
|
-
"patch",
|
|
69
|
-
"manifest",
|
|
70
|
-
"archive"
|
|
71
|
-
];
|
|
72
|
-
/** A storage error code or an Android exit reason: letters, digits, and `._-`. */
|
|
73
|
-
const CODE = /^[A-Za-z0-9._-]{1,64}$/;
|
|
74
|
-
const readCode = (value) => typeof value === "string" && CODE.test(value) ? value : void 0;
|
|
75
|
-
const readMetadata = (payload) => isRecord(payload.metadata) ? payload.metadata : {};
|
|
76
|
-
/**
|
|
77
|
-
* What an UPDATE_FAILED report says failed. It never refuses the report: an
|
|
78
|
-
* unknown value of a set reads as `unknown`, a missing or malformed failure
|
|
79
|
-
* as an unknown stage and reason, and a malformed optional field is left out,
|
|
80
|
-
* as is a null one.
|
|
81
|
-
*/
|
|
82
|
-
function readFailure(value) {
|
|
83
|
-
const failure = isRecord(value) ? value : {};
|
|
84
|
-
const httpStatus = failure.httpStatus;
|
|
85
|
-
const originCode = readCode(failure.originCode);
|
|
86
|
-
const previousProcessExit = readCode(failure.previousProcessExit);
|
|
87
|
-
return {
|
|
88
|
-
stage: oneOf(STAGES, failure.stage),
|
|
89
|
-
reason: oneOf(REASONS, failure.reason),
|
|
90
|
-
...failure.resource == null ? {} : { resource: oneOf(RESOURCES, failure.resource) },
|
|
91
|
-
...Number.isSafeInteger(httpStatus) && httpStatus >= 100 && httpStatus <= 599 ? { httpStatus } : {},
|
|
92
|
-
...failure.transport == null ? {} : { transport: oneOf(TRANSPORTS, failure.transport) },
|
|
93
|
-
...originCode === void 0 ? {} : { originCode },
|
|
94
|
-
...previousProcessExit === void 0 ? {} : { previousProcessExit }
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
async function readBoundedText(request) {
|
|
98
|
-
const contentLength = request.headers.get("content-length");
|
|
99
|
-
const declaredByteLength = Number(contentLength);
|
|
100
|
-
if (contentLength !== null && Number.isSafeInteger(declaredByteLength) && declaredByteLength > 16384) throw new require_errors.InsightsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
|
|
101
|
-
if (request.body === null) return "";
|
|
102
|
-
const reader = request.body.getReader();
|
|
103
|
-
const decoder = new TextDecoder();
|
|
104
|
-
let byteLength = 0;
|
|
105
|
-
let text = "";
|
|
106
|
-
while (true) {
|
|
107
|
-
const result = await reader.read();
|
|
108
|
-
if (result.done) break;
|
|
109
|
-
byteLength += result.value.byteLength;
|
|
110
|
-
if (byteLength > 16384) {
|
|
111
|
-
await reader.cancel();
|
|
112
|
-
throw new require_errors.InsightsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
|
|
113
|
-
}
|
|
114
|
-
text += decoder.decode(result.value, { stream: true });
|
|
115
|
-
}
|
|
116
|
-
return text + decoder.decode();
|
|
117
|
-
}
|
|
118
|
-
async function parseJson(request) {
|
|
119
|
-
const text = await readBoundedText(request);
|
|
120
|
-
try {
|
|
121
|
-
return JSON.parse(text);
|
|
122
|
-
} catch (error) {
|
|
123
|
-
if (error instanceof SyntaxError) throw new require_errors.InsightsBadRequestError("Invalid event payload");
|
|
124
|
-
throw error;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
function requireEvent(payload) {
|
|
128
|
-
if (!isRecord(payload)) throw new require_errors.InsightsBadRequestError("Invalid event payload");
|
|
129
|
-
const platform = requireStringField(payload, "platform");
|
|
130
|
-
if (platform !== "ios" && platform !== "android") throw new require_errors.InsightsBadRequestError("Invalid event field: platform");
|
|
131
|
-
const eventId = readEventId(payload);
|
|
132
|
-
const base = {
|
|
133
|
-
...eventId === void 0 ? {} : { eventId },
|
|
134
|
-
installId: requireIdentityField(payload, "installId"),
|
|
135
|
-
toBundleId: requireStringField(payload, "toBundleId"),
|
|
136
|
-
...payload.userId === void 0 ? {} : { userId: requireIdentityField(payload, "userId") },
|
|
137
|
-
platform,
|
|
138
|
-
appVersion: requireStringField(payload, "appVersion"),
|
|
139
|
-
channel: requireStringField(payload, "channel"),
|
|
140
|
-
cohort: requireStringField(payload, "cohort"),
|
|
141
|
-
fingerprintHash: requireNullableStringField(payload, "fingerprintHash"),
|
|
142
|
-
sdkVersion: payload.sdkVersion === void 0 ? null : requireNullableStringField(payload, "sdkVersion"),
|
|
143
|
-
fromReleaseId: requireNullableStringField(payload, "fromReleaseId"),
|
|
144
|
-
toReleaseId: requireNullableStringField(payload, "toReleaseId")
|
|
145
|
-
};
|
|
146
|
-
const type = requireStringField(payload, "type");
|
|
147
|
-
const movement = () => {
|
|
148
|
-
const updateStrategy = requireStringField(payload, "updateStrategy");
|
|
149
|
-
if (updateStrategy !== "fingerprint" && updateStrategy !== "appVersion") throw new require_errors.InsightsBadRequestError("Invalid event field: updateStrategy");
|
|
150
|
-
return {
|
|
151
|
-
...base,
|
|
152
|
-
fromBundleId: requireStringField(payload, "fromBundleId"),
|
|
153
|
-
updateStrategy
|
|
154
|
-
};
|
|
155
|
-
};
|
|
156
|
-
const metadata = readMetadata(payload);
|
|
157
|
-
switch (type) {
|
|
158
|
-
case "UPDATE_DOWNLOADED": {
|
|
159
|
-
const delivery = metadata.delivery;
|
|
160
|
-
const read = {
|
|
161
|
-
...delivery == null ? {} : { delivery: oneOf(DELIVERIES, delivery) },
|
|
162
|
-
...metadata.patchFallback === true ? { patchFallback: true } : {}
|
|
163
|
-
};
|
|
164
|
-
return {
|
|
165
|
-
...movement(),
|
|
166
|
-
type,
|
|
167
|
-
...Object.keys(read).length === 0 ? {} : { metadata: read }
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
case "UPDATE_APPLIED": return {
|
|
171
|
-
...movement(),
|
|
172
|
-
type
|
|
173
|
-
};
|
|
174
|
-
case "RECOVERED": {
|
|
175
|
-
const previousProcessExit = readCode(metadata.previousProcessExit);
|
|
176
|
-
return {
|
|
177
|
-
...movement(),
|
|
178
|
-
type,
|
|
179
|
-
...previousProcessExit === void 0 ? {} : { metadata: { previousProcessExit } }
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
case "UPDATE_FAILED": return {
|
|
183
|
-
...movement(),
|
|
184
|
-
type,
|
|
185
|
-
metadata: { failure: readFailure(metadata.failure) }
|
|
186
|
-
};
|
|
187
|
-
case "UNCHANGED":
|
|
188
|
-
if (payload.fromBundleId !== null || payload.updateStrategy !== null) throw new require_errors.InsightsBadRequestError("Invalid unchanged event shape");
|
|
189
|
-
return {
|
|
190
|
-
...base,
|
|
191
|
-
type,
|
|
192
|
-
fromBundleId: null,
|
|
193
|
-
updateStrategy: null
|
|
194
|
-
};
|
|
195
|
-
default: throw new require_errors.InsightsBadRequestError("Invalid event field: type");
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
async function parseBundleEventRequest(request) {
|
|
199
|
-
return requireEvent(await parseJson(request));
|
|
200
|
-
}
|
|
201
|
-
function createBundleEventRow(input) {
|
|
202
|
-
input = requireEvent(input);
|
|
203
|
-
const base = {
|
|
204
|
-
app_version: input.appVersion,
|
|
205
|
-
channel: input.channel,
|
|
206
|
-
from_release_id: input.fromReleaseId,
|
|
207
|
-
id: input.eventId ?? (0, _hot_updater_plugin_core.createUUIDv7)(),
|
|
208
|
-
install_id: input.installId,
|
|
209
|
-
platform: input.platform,
|
|
210
|
-
received_at_ms: Date.now(),
|
|
211
|
-
to_bundle_id: input.toBundleId,
|
|
212
|
-
to_release_id: input.toReleaseId,
|
|
213
|
-
user_id: input.userId ?? null
|
|
214
|
-
};
|
|
215
|
-
const metadata = {
|
|
216
|
-
cohort: input.cohort,
|
|
217
|
-
fingerprint_hash: input.fingerprintHash,
|
|
218
|
-
sdk_version: input.sdkVersion ?? null,
|
|
219
|
-
update_strategy: input.updateStrategy
|
|
220
|
-
};
|
|
221
|
-
switch (input.type) {
|
|
222
|
-
case "UPDATE_DOWNLOADED": {
|
|
223
|
-
const { delivery, patchFallback } = input.metadata ?? {};
|
|
224
|
-
return {
|
|
225
|
-
...base,
|
|
226
|
-
from_bundle_id: input.fromBundleId,
|
|
227
|
-
type: input.type,
|
|
228
|
-
metadata: {
|
|
229
|
-
...metadata,
|
|
230
|
-
...delivery === void 0 ? {} : { delivery },
|
|
231
|
-
...patchFallback ? { patch_fallback: true } : {}
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
case "UPDATE_APPLIED": return {
|
|
236
|
-
...base,
|
|
237
|
-
from_bundle_id: input.fromBundleId,
|
|
238
|
-
type: input.type,
|
|
239
|
-
metadata
|
|
240
|
-
};
|
|
241
|
-
case "RECOVERED": {
|
|
242
|
-
const exit = input.metadata?.previousProcessExit;
|
|
243
|
-
return {
|
|
244
|
-
...base,
|
|
245
|
-
from_bundle_id: input.fromBundleId,
|
|
246
|
-
type: input.type,
|
|
247
|
-
metadata: {
|
|
248
|
-
...metadata,
|
|
249
|
-
...exit === void 0 ? {} : { previous_process_exit: exit }
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
case "UPDATE_FAILED": {
|
|
254
|
-
const { failure } = input.metadata;
|
|
255
|
-
return {
|
|
256
|
-
...base,
|
|
257
|
-
from_bundle_id: input.fromBundleId,
|
|
258
|
-
type: input.type,
|
|
259
|
-
metadata: {
|
|
260
|
-
...metadata,
|
|
261
|
-
failure: {
|
|
262
|
-
stage: failure.stage,
|
|
263
|
-
reason: failure.reason,
|
|
264
|
-
...failure.resource === void 0 ? {} : { resource: failure.resource },
|
|
265
|
-
...failure.httpStatus === void 0 ? {} : { http_status: failure.httpStatus },
|
|
266
|
-
...failure.transport === void 0 ? {} : { transport: failure.transport },
|
|
267
|
-
...failure.originCode === void 0 ? {} : { origin_code: failure.originCode },
|
|
268
|
-
...failure.previousProcessExit === void 0 ? {} : { previous_process_exit: failure.previousProcessExit }
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
case "UNCHANGED": return {
|
|
274
|
-
...base,
|
|
275
|
-
from_bundle_id: null,
|
|
276
|
-
type: input.type,
|
|
277
|
-
metadata
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
//#endregion
|
|
282
|
-
exports.EVENT_BODY_MAX_BYTES = EVENT_BODY_MAX_BYTES;
|
|
283
|
-
exports.createBundleEventRow = createBundleEventRow;
|
|
284
|
-
exports.parseBundleEventRequest = parseBundleEventRequest;
|
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
import { InsightsBadRequestError, InsightsPayloadTooLargeError } from "./errors.mjs";
|
|
2
|
-
import { createUUIDv7, isUUIDv7 } from "@hot-updater/plugin-core";
|
|
3
|
-
//#region src/plugins/insights/eventInput.ts
|
|
4
|
-
const MAX_EVENT_STRING_LENGTH = 1024;
|
|
5
|
-
const MAX_IDENTITY_LENGTH = 255;
|
|
6
|
-
const EVENT_BODY_MAX_BYTES = 16384;
|
|
7
|
-
function isRecord(value) {
|
|
8
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
|
-
}
|
|
10
|
-
function requireStringField(payload, key) {
|
|
11
|
-
const value = payload[key];
|
|
12
|
-
if (typeof value !== "string" || value.length === 0 || value.length > MAX_EVENT_STRING_LENGTH || new TextDecoder("utf-8", { ignoreBOM: true }).decode(new TextEncoder().encode(value)) !== value) throw new InsightsBadRequestError(`Invalid event field: ${key}`);
|
|
13
|
-
return value;
|
|
14
|
-
}
|
|
15
|
-
function requireNullableStringField(payload, key) {
|
|
16
|
-
if (payload[key] === null) return null;
|
|
17
|
-
return requireStringField(payload, key);
|
|
18
|
-
}
|
|
19
|
-
function requireIdentityField(payload, key) {
|
|
20
|
-
const value = requireStringField(payload, key);
|
|
21
|
-
if (value.length > MAX_IDENTITY_LENGTH) throw new InsightsBadRequestError(`Invalid event field: ${key}`);
|
|
22
|
-
return value;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* The report's idempotency key, when the client sends one: it creates the
|
|
26
|
-
* UUIDv7 once and repeats it on every retry of that report.
|
|
27
|
-
*/
|
|
28
|
-
function readEventId(payload) {
|
|
29
|
-
const value = payload.eventId;
|
|
30
|
-
if (value === void 0) return void 0;
|
|
31
|
-
if (!isUUIDv7(value)) throw new InsightsBadRequestError("Invalid event field: eventId");
|
|
32
|
-
return value;
|
|
33
|
-
}
|
|
34
|
-
/** One value of an open set: any other value reads as `unknown`. */
|
|
35
|
-
const oneOf = (values, value) => values.includes(value) ? value : "unknown";
|
|
36
|
-
const STAGES = [
|
|
37
|
-
"check",
|
|
38
|
-
"download",
|
|
39
|
-
"install"
|
|
40
|
-
];
|
|
41
|
-
const REASONS = [
|
|
42
|
-
"network",
|
|
43
|
-
"http",
|
|
44
|
-
"invalid_response",
|
|
45
|
-
"hash_mismatch",
|
|
46
|
-
"signature",
|
|
47
|
-
"patch",
|
|
48
|
-
"extract",
|
|
49
|
-
"storage"
|
|
50
|
-
];
|
|
51
|
-
const RESOURCES = [
|
|
52
|
-
"catalog",
|
|
53
|
-
"artifact",
|
|
54
|
-
"manifest",
|
|
55
|
-
"file",
|
|
56
|
-
"patch",
|
|
57
|
-
"archive"
|
|
58
|
-
];
|
|
59
|
-
const TRANSPORTS = [
|
|
60
|
-
"timeout",
|
|
61
|
-
"dns",
|
|
62
|
-
"tls",
|
|
63
|
-
"connection",
|
|
64
|
-
"offline",
|
|
65
|
-
"cancelled"
|
|
66
|
-
];
|
|
67
|
-
const DELIVERIES = [
|
|
68
|
-
"patch",
|
|
69
|
-
"manifest",
|
|
70
|
-
"archive"
|
|
71
|
-
];
|
|
72
|
-
/** A storage error code or an Android exit reason: letters, digits, and `._-`. */
|
|
73
|
-
const CODE = /^[A-Za-z0-9._-]{1,64}$/;
|
|
74
|
-
const readCode = (value) => typeof value === "string" && CODE.test(value) ? value : void 0;
|
|
75
|
-
const readMetadata = (payload) => isRecord(payload.metadata) ? payload.metadata : {};
|
|
76
|
-
/**
|
|
77
|
-
* What an UPDATE_FAILED report says failed. It never refuses the report: an
|
|
78
|
-
* unknown value of a set reads as `unknown`, a missing or malformed failure
|
|
79
|
-
* as an unknown stage and reason, and a malformed optional field is left out,
|
|
80
|
-
* as is a null one.
|
|
81
|
-
*/
|
|
82
|
-
function readFailure(value) {
|
|
83
|
-
const failure = isRecord(value) ? value : {};
|
|
84
|
-
const httpStatus = failure.httpStatus;
|
|
85
|
-
const originCode = readCode(failure.originCode);
|
|
86
|
-
const previousProcessExit = readCode(failure.previousProcessExit);
|
|
87
|
-
return {
|
|
88
|
-
stage: oneOf(STAGES, failure.stage),
|
|
89
|
-
reason: oneOf(REASONS, failure.reason),
|
|
90
|
-
...failure.resource == null ? {} : { resource: oneOf(RESOURCES, failure.resource) },
|
|
91
|
-
...Number.isSafeInteger(httpStatus) && httpStatus >= 100 && httpStatus <= 599 ? { httpStatus } : {},
|
|
92
|
-
...failure.transport == null ? {} : { transport: oneOf(TRANSPORTS, failure.transport) },
|
|
93
|
-
...originCode === void 0 ? {} : { originCode },
|
|
94
|
-
...previousProcessExit === void 0 ? {} : { previousProcessExit }
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
async function readBoundedText(request) {
|
|
98
|
-
const contentLength = request.headers.get("content-length");
|
|
99
|
-
const declaredByteLength = Number(contentLength);
|
|
100
|
-
if (contentLength !== null && Number.isSafeInteger(declaredByteLength) && declaredByteLength > 16384) throw new InsightsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
|
|
101
|
-
if (request.body === null) return "";
|
|
102
|
-
const reader = request.body.getReader();
|
|
103
|
-
const decoder = new TextDecoder();
|
|
104
|
-
let byteLength = 0;
|
|
105
|
-
let text = "";
|
|
106
|
-
while (true) {
|
|
107
|
-
const result = await reader.read();
|
|
108
|
-
if (result.done) break;
|
|
109
|
-
byteLength += result.value.byteLength;
|
|
110
|
-
if (byteLength > 16384) {
|
|
111
|
-
await reader.cancel();
|
|
112
|
-
throw new InsightsPayloadTooLargeError(EVENT_BODY_MAX_BYTES);
|
|
113
|
-
}
|
|
114
|
-
text += decoder.decode(result.value, { stream: true });
|
|
115
|
-
}
|
|
116
|
-
return text + decoder.decode();
|
|
117
|
-
}
|
|
118
|
-
async function parseJson(request) {
|
|
119
|
-
const text = await readBoundedText(request);
|
|
120
|
-
try {
|
|
121
|
-
return JSON.parse(text);
|
|
122
|
-
} catch (error) {
|
|
123
|
-
if (error instanceof SyntaxError) throw new InsightsBadRequestError("Invalid event payload");
|
|
124
|
-
throw error;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
function requireEvent(payload) {
|
|
128
|
-
if (!isRecord(payload)) throw new InsightsBadRequestError("Invalid event payload");
|
|
129
|
-
const platform = requireStringField(payload, "platform");
|
|
130
|
-
if (platform !== "ios" && platform !== "android") throw new InsightsBadRequestError("Invalid event field: platform");
|
|
131
|
-
const eventId = readEventId(payload);
|
|
132
|
-
const base = {
|
|
133
|
-
...eventId === void 0 ? {} : { eventId },
|
|
134
|
-
installId: requireIdentityField(payload, "installId"),
|
|
135
|
-
toBundleId: requireStringField(payload, "toBundleId"),
|
|
136
|
-
...payload.userId === void 0 ? {} : { userId: requireIdentityField(payload, "userId") },
|
|
137
|
-
platform,
|
|
138
|
-
appVersion: requireStringField(payload, "appVersion"),
|
|
139
|
-
channel: requireStringField(payload, "channel"),
|
|
140
|
-
cohort: requireStringField(payload, "cohort"),
|
|
141
|
-
fingerprintHash: requireNullableStringField(payload, "fingerprintHash"),
|
|
142
|
-
sdkVersion: payload.sdkVersion === void 0 ? null : requireNullableStringField(payload, "sdkVersion"),
|
|
143
|
-
fromReleaseId: requireNullableStringField(payload, "fromReleaseId"),
|
|
144
|
-
toReleaseId: requireNullableStringField(payload, "toReleaseId")
|
|
145
|
-
};
|
|
146
|
-
const type = requireStringField(payload, "type");
|
|
147
|
-
const movement = () => {
|
|
148
|
-
const updateStrategy = requireStringField(payload, "updateStrategy");
|
|
149
|
-
if (updateStrategy !== "fingerprint" && updateStrategy !== "appVersion") throw new InsightsBadRequestError("Invalid event field: updateStrategy");
|
|
150
|
-
return {
|
|
151
|
-
...base,
|
|
152
|
-
fromBundleId: requireStringField(payload, "fromBundleId"),
|
|
153
|
-
updateStrategy
|
|
154
|
-
};
|
|
155
|
-
};
|
|
156
|
-
const metadata = readMetadata(payload);
|
|
157
|
-
switch (type) {
|
|
158
|
-
case "UPDATE_DOWNLOADED": {
|
|
159
|
-
const delivery = metadata.delivery;
|
|
160
|
-
const read = {
|
|
161
|
-
...delivery == null ? {} : { delivery: oneOf(DELIVERIES, delivery) },
|
|
162
|
-
...metadata.patchFallback === true ? { patchFallback: true } : {}
|
|
163
|
-
};
|
|
164
|
-
return {
|
|
165
|
-
...movement(),
|
|
166
|
-
type,
|
|
167
|
-
...Object.keys(read).length === 0 ? {} : { metadata: read }
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
case "UPDATE_APPLIED": return {
|
|
171
|
-
...movement(),
|
|
172
|
-
type
|
|
173
|
-
};
|
|
174
|
-
case "RECOVERED": {
|
|
175
|
-
const previousProcessExit = readCode(metadata.previousProcessExit);
|
|
176
|
-
return {
|
|
177
|
-
...movement(),
|
|
178
|
-
type,
|
|
179
|
-
...previousProcessExit === void 0 ? {} : { metadata: { previousProcessExit } }
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
case "UPDATE_FAILED": return {
|
|
183
|
-
...movement(),
|
|
184
|
-
type,
|
|
185
|
-
metadata: { failure: readFailure(metadata.failure) }
|
|
186
|
-
};
|
|
187
|
-
case "UNCHANGED":
|
|
188
|
-
if (payload.fromBundleId !== null || payload.updateStrategy !== null) throw new InsightsBadRequestError("Invalid unchanged event shape");
|
|
189
|
-
return {
|
|
190
|
-
...base,
|
|
191
|
-
type,
|
|
192
|
-
fromBundleId: null,
|
|
193
|
-
updateStrategy: null
|
|
194
|
-
};
|
|
195
|
-
default: throw new InsightsBadRequestError("Invalid event field: type");
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
async function parseBundleEventRequest(request) {
|
|
199
|
-
return requireEvent(await parseJson(request));
|
|
200
|
-
}
|
|
201
|
-
function createBundleEventRow(input) {
|
|
202
|
-
input = requireEvent(input);
|
|
203
|
-
const base = {
|
|
204
|
-
app_version: input.appVersion,
|
|
205
|
-
channel: input.channel,
|
|
206
|
-
from_release_id: input.fromReleaseId,
|
|
207
|
-
id: input.eventId ?? createUUIDv7(),
|
|
208
|
-
install_id: input.installId,
|
|
209
|
-
platform: input.platform,
|
|
210
|
-
received_at_ms: Date.now(),
|
|
211
|
-
to_bundle_id: input.toBundleId,
|
|
212
|
-
to_release_id: input.toReleaseId,
|
|
213
|
-
user_id: input.userId ?? null
|
|
214
|
-
};
|
|
215
|
-
const metadata = {
|
|
216
|
-
cohort: input.cohort,
|
|
217
|
-
fingerprint_hash: input.fingerprintHash,
|
|
218
|
-
sdk_version: input.sdkVersion ?? null,
|
|
219
|
-
update_strategy: input.updateStrategy
|
|
220
|
-
};
|
|
221
|
-
switch (input.type) {
|
|
222
|
-
case "UPDATE_DOWNLOADED": {
|
|
223
|
-
const { delivery, patchFallback } = input.metadata ?? {};
|
|
224
|
-
return {
|
|
225
|
-
...base,
|
|
226
|
-
from_bundle_id: input.fromBundleId,
|
|
227
|
-
type: input.type,
|
|
228
|
-
metadata: {
|
|
229
|
-
...metadata,
|
|
230
|
-
...delivery === void 0 ? {} : { delivery },
|
|
231
|
-
...patchFallback ? { patch_fallback: true } : {}
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
case "UPDATE_APPLIED": return {
|
|
236
|
-
...base,
|
|
237
|
-
from_bundle_id: input.fromBundleId,
|
|
238
|
-
type: input.type,
|
|
239
|
-
metadata
|
|
240
|
-
};
|
|
241
|
-
case "RECOVERED": {
|
|
242
|
-
const exit = input.metadata?.previousProcessExit;
|
|
243
|
-
return {
|
|
244
|
-
...base,
|
|
245
|
-
from_bundle_id: input.fromBundleId,
|
|
246
|
-
type: input.type,
|
|
247
|
-
metadata: {
|
|
248
|
-
...metadata,
|
|
249
|
-
...exit === void 0 ? {} : { previous_process_exit: exit }
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
case "UPDATE_FAILED": {
|
|
254
|
-
const { failure } = input.metadata;
|
|
255
|
-
return {
|
|
256
|
-
...base,
|
|
257
|
-
from_bundle_id: input.fromBundleId,
|
|
258
|
-
type: input.type,
|
|
259
|
-
metadata: {
|
|
260
|
-
...metadata,
|
|
261
|
-
failure: {
|
|
262
|
-
stage: failure.stage,
|
|
263
|
-
reason: failure.reason,
|
|
264
|
-
...failure.resource === void 0 ? {} : { resource: failure.resource },
|
|
265
|
-
...failure.httpStatus === void 0 ? {} : { http_status: failure.httpStatus },
|
|
266
|
-
...failure.transport === void 0 ? {} : { transport: failure.transport },
|
|
267
|
-
...failure.originCode === void 0 ? {} : { origin_code: failure.originCode },
|
|
268
|
-
...failure.previousProcessExit === void 0 ? {} : { previous_process_exit: failure.previousProcessExit }
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
case "UNCHANGED": return {
|
|
274
|
-
...base,
|
|
275
|
-
from_bundle_id: null,
|
|
276
|
-
type: input.type,
|
|
277
|
-
metadata
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
//#endregion
|
|
282
|
-
export { EVENT_BODY_MAX_BYTES, createBundleEventRow, parseBundleEventRequest };
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
2
|
-
let _hot_updater_plugin_core_internal = require("@hot-updater/plugin-core/internal");
|
|
3
|
-
//#region src/plugins/insights/eventRow.ts
|
|
4
|
-
const isOptional = (value, key, valid) => !Object.hasOwn(value, key) || valid(value[key]);
|
|
5
|
-
const isString = (value) => typeof value === "string";
|
|
6
|
-
/** An `UPDATE_FAILED` report's stored failure: a stage and a reason, and what else the client knew. */
|
|
7
|
-
const isDatabaseBundleEventFailure = (value) => (0, _hot_updater_plugin_core_internal.isDatabaseJsonObject)(value) && isString(value.stage) && isString(value.reason) && isOptional(value, "resource", isString) && isOptional(value, "http_status", (status) => Number.isSafeInteger(status)) && isOptional(value, "transport", isString) && isOptional(value, "origin_code", isString) && isOptional(value, "previous_process_exit", isString);
|
|
8
|
-
const isDatabaseBundleEventMetadata = (value) => (0, _hot_updater_plugin_core_internal.isDatabaseJsonObject)(value) && typeof value.cohort === "string" && (value.update_strategy === null || value.update_strategy === "fingerprint" || value.update_strategy === "appVersion") && (value.fingerprint_hash === null || typeof value.fingerprint_hash === "string") && (value.sdk_version === null || typeof value.sdk_version === "string") && isOptional(value, "failure", isDatabaseBundleEventFailure) && isOptional(value, "delivery", isString) && isOptional(value, "patch_fallback", (flag) => typeof flag === "boolean") && isOptional(value, "previous_process_exit", isString);
|
|
9
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10
|
-
const isIdentity = (value) => typeof value === "string" && value.length > 0 && value.length <= 255;
|
|
11
|
-
const isTextOrNull = (value) => value === null || typeof value === "string";
|
|
12
|
-
/** Each bundle event field and what it holds. */
|
|
13
|
-
const BUNDLE_EVENT_FIELDS = {
|
|
14
|
-
id: (value) => typeof value === "string",
|
|
15
|
-
type: (value) => value === "UPDATE_DOWNLOADED" || value === "UPDATE_APPLIED" || value === "RECOVERED" || value === "UPDATE_FAILED" || value === "UNCHANGED",
|
|
16
|
-
install_id: isIdentity,
|
|
17
|
-
user_id: (value) => value === null || isIdentity(value),
|
|
18
|
-
from_bundle_id: isTextOrNull,
|
|
19
|
-
from_release_id: isTextOrNull,
|
|
20
|
-
to_release_id: isTextOrNull,
|
|
21
|
-
to_bundle_id: (value) => typeof value === "string",
|
|
22
|
-
platform: (value) => value === "ios" || value === "android",
|
|
23
|
-
app_version: (value) => typeof value === "string",
|
|
24
|
-
channel: (value) => typeof value === "string",
|
|
25
|
-
metadata: isDatabaseBundleEventMetadata,
|
|
26
|
-
received_at_ms: (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0
|
|
27
|
-
};
|
|
28
|
-
const updateStrategyOf = (row) => isRecord(row.metadata) ? row.metadata.update_strategy : void 0;
|
|
29
|
-
/**
|
|
30
|
-
* A movement, or a failed update, names the bundle it left and how the
|
|
31
|
-
* device updates, and a failed update says what failed; an unchanged report
|
|
32
|
-
* names neither.
|
|
33
|
-
*/
|
|
34
|
-
const hasEventInvariants = (row) => (row.type === "UPDATE_DOWNLOADED" || row.type === "UPDATE_APPLIED" || row.type === "RECOVERED" || row.type === "UPDATE_FAILED") && typeof row.from_bundle_id === "string" && (updateStrategyOf(row) === "fingerprint" || updateStrategyOf(row) === "appVersion") && (row.type !== "UPDATE_FAILED" || isRecord(row.metadata) && isRecord(row.metadata.failure)) || row.type === "UNCHANGED" && row.from_bundle_id === null && updateStrategyOf(row) === null;
|
|
35
|
-
/**
|
|
36
|
-
* Throws unless `row` has exactly the bundle event fields, each of its type,
|
|
37
|
-
* and the invariants of its event type: `invalid-field` for an unknown field,
|
|
38
|
-
* `invalid-data` for anything else.
|
|
39
|
-
*/
|
|
40
|
-
const validateBundleEventFields = (row) => {
|
|
41
|
-
if (!isRecord(row)) throw new _hot_updater_plugin_core.DatabasePluginInputError("invalid-data");
|
|
42
|
-
for (const field of Object.keys(row)) if (!Object.hasOwn(BUNDLE_EVENT_FIELDS, field)) throw new _hot_updater_plugin_core.DatabasePluginInputError("invalid-field");
|
|
43
|
-
for (const [field, valid] of Object.entries(BUNDLE_EVENT_FIELDS)) if (!Object.hasOwn(row, field) || !valid(row[field])) throw new _hot_updater_plugin_core.DatabasePluginInputError("invalid-data");
|
|
44
|
-
if (!hasEventInvariants(row)) throw new _hot_updater_plugin_core.DatabasePluginInputError("invalid-data");
|
|
45
|
-
};
|
|
46
|
-
//#endregion
|
|
47
|
-
exports.isDatabaseBundleEventMetadata = isDatabaseBundleEventMetadata;
|
|
48
|
-
exports.isRecord = isRecord;
|
|
49
|
-
exports.validateBundleEventFields = validateBundleEventFields;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { DatabaseJsonObject, Platform } from "@hot-updater/plugin-core";
|
|
2
|
-
//#region src/plugins/insights/eventRow.d.ts
|
|
3
|
-
/** Where an update failed, and what failed; open sets, `unknown` for any other value. */
|
|
4
|
-
type BundleEventFailureStage = "check" | "download" | "install" | "unknown";
|
|
5
|
-
type BundleEventFailureReason = "network" | "http" | "invalid_response" | "hash_mismatch" | "signature" | "patch" | "extract" | "storage" | "unknown";
|
|
6
|
-
/** An `UPDATE_FAILED` report's failure, as stored. */
|
|
7
|
-
type BundleEventFailure = DatabaseJsonObject & {
|
|
8
|
-
readonly stage: BundleEventFailureStage;
|
|
9
|
-
readonly reason: BundleEventFailureReason;
|
|
10
|
-
/** What the client was fetching or writing. */
|
|
11
|
-
readonly resource?: "catalog" | "artifact" | "manifest" | "file" | "patch" | "archive" | "unknown";
|
|
12
|
-
readonly http_status?: number;
|
|
13
|
-
/** How the connection failed, when it did. */
|
|
14
|
-
readonly transport?: "timeout" | "dns" | "tls" | "connection" | "offline" | "cancelled" | "unknown";
|
|
15
|
-
/** The storage origin's error code, such as `ExpiredToken`. */
|
|
16
|
-
readonly origin_code?: string;
|
|
17
|
-
/** Android's `ApplicationExitInfo` reason for the process before this one. */
|
|
18
|
-
readonly previous_process_exit?: string;
|
|
19
|
-
};
|
|
20
|
-
/** Ancillary report data; queryable identity and lifecycle fields stay on the row. */
|
|
21
|
-
type DatabaseBundleEventMetadata = DatabaseJsonObject & {
|
|
22
|
-
readonly cohort: string;
|
|
23
|
-
readonly update_strategy: "fingerprint" | "appVersion" | null;
|
|
24
|
-
readonly fingerprint_hash: string | null;
|
|
25
|
-
readonly sdk_version: string | null;
|
|
26
|
-
/** `UPDATE_FAILED`: what failed. */
|
|
27
|
-
readonly failure?: BundleEventFailure;
|
|
28
|
-
/** `UPDATE_DOWNLOADED`: how the bundle arrived. */
|
|
29
|
-
readonly delivery?: "patch" | "manifest" | "archive" | "unknown";
|
|
30
|
-
/** `UPDATE_DOWNLOADED`: a patch failed and the full files came instead. */
|
|
31
|
-
readonly patch_fallback?: boolean;
|
|
32
|
-
/** `RECOVERED`: Android's `ApplicationExitInfo` reason for the crashed process. */
|
|
33
|
-
readonly previous_process_exit?: string;
|
|
34
|
-
};
|
|
35
|
-
type BundleEventRowBase = {
|
|
36
|
-
readonly id: string;
|
|
37
|
-
readonly install_id: string;
|
|
38
|
-
readonly user_id: string | null;
|
|
39
|
-
readonly from_release_id: string | null;
|
|
40
|
-
readonly to_release_id: string | null;
|
|
41
|
-
readonly to_bundle_id: string;
|
|
42
|
-
readonly platform: Platform;
|
|
43
|
-
readonly app_version: string;
|
|
44
|
-
readonly channel: string;
|
|
45
|
-
readonly metadata: DatabaseBundleEventMetadata;
|
|
46
|
-
readonly received_at_ms: number;
|
|
47
|
-
};
|
|
48
|
-
type BundleEventRow = BundleEventRowBase & ({
|
|
49
|
-
readonly type: "UPDATE_DOWNLOADED";
|
|
50
|
-
readonly from_bundle_id: string;
|
|
51
|
-
} | {
|
|
52
|
-
readonly type: "UPDATE_APPLIED" | "RECOVERED";
|
|
53
|
-
readonly from_bundle_id: string;
|
|
54
|
-
} |
|
|
55
|
-
/** An update that failed: `from` is the running bundle, `to` the target (for a check, the running bundle). */
|
|
56
|
-
{
|
|
57
|
-
readonly type: "UPDATE_FAILED";
|
|
58
|
-
readonly from_bundle_id: string;
|
|
59
|
-
} | {
|
|
60
|
-
readonly type: "UNCHANGED";
|
|
61
|
-
readonly from_bundle_id: null;
|
|
62
|
-
});
|
|
63
|
-
//#endregion
|
|
64
|
-
export { BundleEventFailure, BundleEventFailureReason, BundleEventFailureStage, BundleEventRow, BundleEventRowBase, DatabaseBundleEventMetadata };
|