@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,196 +0,0 @@
|
|
|
1
|
-
import { physicalRetention, retentionProblems } from "./retention.mjs";
|
|
2
|
-
import { DATABASE_VERSION_COLUMN, DatabaseSchemaError } from "@hot-updater/plugin-core/internal";
|
|
3
|
-
//#region src/database/resolveSchema.ts
|
|
4
|
-
const SHARD_COLUMN = "_shard";
|
|
5
|
-
const MAX_SHARDS = 64;
|
|
6
|
-
const NAME = /^[a-z][a-z0-9_]*$/u;
|
|
7
|
-
const INDEX_NAME = /^[A-Za-z][A-Za-z0-9_]*$/u;
|
|
8
|
-
const tableName = (module, model) => module.namespace ? `${module.namespace}_${model}` : model;
|
|
9
|
-
const integer = (name, defaulted = false) => ({
|
|
10
|
-
name,
|
|
11
|
-
type: "integer",
|
|
12
|
-
nullable: false,
|
|
13
|
-
...defaulted ? { default: 0 } : {}
|
|
14
|
-
});
|
|
15
|
-
/** A declared or derived field's type, and whether it holds several values. */
|
|
16
|
-
const fieldType = (model, name) => {
|
|
17
|
-
const field = model.fields[name] ?? (model.kind === "table" ? model.derived[name] : void 0);
|
|
18
|
-
return field && {
|
|
19
|
-
type: field.type,
|
|
20
|
-
multi: "multi" in field && !!field.multi
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
const metricsOf = (model) => [
|
|
24
|
-
...model.counters,
|
|
25
|
-
...model.gauges,
|
|
26
|
-
...model.distinct
|
|
27
|
-
];
|
|
28
|
-
/** Field names, the key, and each field's options. */
|
|
29
|
-
const fieldProblems = (definition, add) => {
|
|
30
|
-
const names = [...Object.keys(definition.fields), ...definition.kind === "table" ? Object.keys(definition.derived) : metricsOf(definition)];
|
|
31
|
-
for (const name of new Set(names)) {
|
|
32
|
-
if (!NAME.test(name)) add(`field "${name}" must match ${NAME.source}`);
|
|
33
|
-
if (names.indexOf(name) !== names.lastIndexOf(name)) add(`field "${name}" is declared twice`);
|
|
34
|
-
}
|
|
35
|
-
const { key } = definition;
|
|
36
|
-
if (key.length === 0) add("key is empty");
|
|
37
|
-
if (new Set(key).size !== key.length) add("key repeats a field");
|
|
38
|
-
for (const name of key) {
|
|
39
|
-
const field = definition.fields[name];
|
|
40
|
-
if (field === void 0) add(`key field "${name}" is not a declared field`);
|
|
41
|
-
else if (field.required === false) add(`key field "${name}" is nullable`);
|
|
42
|
-
else if (field.type === "json") add(`key field "${name}" is json`);
|
|
43
|
-
}
|
|
44
|
-
for (const [name, { type, maxLength, ascii }] of Object.entries(definition.fields)) {
|
|
45
|
-
if (maxLength !== void 0 && (type !== "string" || !Number.isSafeInteger(maxLength) || maxLength < 1)) add(`field "${name}" has an invalid maxLength`);
|
|
46
|
-
if (ascii && type !== "string") add(`field "${name}" is ascii but not a string`);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
/** A table's derived fields and references. */
|
|
50
|
-
const tableProblems = (definition, add, table) => {
|
|
51
|
-
for (const [name, derived] of Object.entries(definition.derived)) {
|
|
52
|
-
if (typeof derived.compute !== "function") add(`derived field "${name}" has no compute function`);
|
|
53
|
-
if (derived.multi && derived.type === "json") add(`derived field "${name}" cannot be multi-valued json`);
|
|
54
|
-
}
|
|
55
|
-
for (const [name, { type, references }] of Object.entries(definition.fields)) {
|
|
56
|
-
if (references === void 0) continue;
|
|
57
|
-
const target = table(references.model);
|
|
58
|
-
const targetKey = target?.key.length === 1 ? target.fields[target.key[0]] : void 0;
|
|
59
|
-
if (targetKey === void 0) add(`field "${name}" references "${references.model}", which is not a single-key table of this module`);
|
|
60
|
-
else if (targetKey.type !== type) add(`field "${name}" and the key of "${references.model}" differ in type`);
|
|
61
|
-
if (references.onDelete === "cascade" && !Object.values(definition.indexes).some(({ eq }) => eq.length === 1 && eq[0] === name)) add(`cascade on "${name}" needs an index whose eq is exactly [${name}]`);
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
/** An aggregate's identity, metrics, and shards. */
|
|
65
|
-
const aggregateProblems = (definition, add) => {
|
|
66
|
-
const identity = Object.keys(definition.fields);
|
|
67
|
-
if (definition.key.join("\0") !== identity.join("\0")) add(`key must list the identity fields in declaration order: ${identity.join(", ")}`);
|
|
68
|
-
if (metricsOf(definition).length === 0) add("aggregate has no metrics");
|
|
69
|
-
if (definition.distinct.length > 0 && definition.counters.length + definition.gauges.length > 0) add("distinct sketches need an aggregate of their own");
|
|
70
|
-
const { shards } = definition;
|
|
71
|
-
if (!Number.isSafeInteger(shards) || shards < 1 || shards > 64) add(`shards must be 1–64`);
|
|
72
|
-
};
|
|
73
|
-
/** Every problem in one model's declaration, its roots and references included. */
|
|
74
|
-
const problemsOf = (module, model, definition) => {
|
|
75
|
-
const problems = [];
|
|
76
|
-
const add = (message) => problems.push(`${module.id}.${model}: ${message}`);
|
|
77
|
-
const table = (name) => {
|
|
78
|
-
const target = module.schema[name];
|
|
79
|
-
return target?.kind === "table" ? target : void 0;
|
|
80
|
-
};
|
|
81
|
-
if (!NAME.test(model)) add("model names use lowercase letters, digits, and _");
|
|
82
|
-
fieldProblems(definition, add);
|
|
83
|
-
for (const [name, index] of Object.entries(definition.indexes)) {
|
|
84
|
-
const columns = [...index.eq, ...index.sort];
|
|
85
|
-
if (!INDEX_NAME.test(name)) add(`index "${name}" must match ${INDEX_NAME.source}`);
|
|
86
|
-
if (columns.length === 0) add(`index "${name}" has no fields`);
|
|
87
|
-
if (index.unique && index.sort.length > 0) add(`unique index "${name}" cannot sort`);
|
|
88
|
-
if (columns.filter((column) => {
|
|
89
|
-
const type = fieldType(definition, column);
|
|
90
|
-
if (type === void 0) add(`index "${name}" names undeclared field "${column}"`);
|
|
91
|
-
else if (type.type === "json") add(`index "${name}" names json field "${column}"`);
|
|
92
|
-
else if (type.multi && index.sort.includes(column)) add(`index "${name}" sorts by multi-valued field "${column}"`);
|
|
93
|
-
return type?.type !== "json" && type?.multi;
|
|
94
|
-
}).length > 1) add(`index "${name}" has more than one multi-valued field`);
|
|
95
|
-
if (index.root === void 0) continue;
|
|
96
|
-
const root = table(index.root.model);
|
|
97
|
-
if (root === void 0) add(`index "${name}" is rooted at unknown table "${index.root.model}"`);
|
|
98
|
-
else if (root.key.length > index.eq.length || root.key.some((field, position) => fieldType(definition, index.eq[position])?.type !== root.fields[field].type)) add(`index "${name}" eq must start with the key of "${index.root.model}"`);
|
|
99
|
-
}
|
|
100
|
-
if (definition.kind === "table") tableProblems(definition, add, table);
|
|
101
|
-
else aggregateProblems(definition, add);
|
|
102
|
-
for (const problem of retentionProblems(module.schema, model)) add(problem);
|
|
103
|
-
return problems;
|
|
104
|
-
};
|
|
105
|
-
/** Rejects invalid module schemas at startup, listing every problem. */
|
|
106
|
-
const validateSchema = (modules) => {
|
|
107
|
-
const problems = [];
|
|
108
|
-
const owners = /* @__PURE__ */ new Map();
|
|
109
|
-
for (const module of modules) for (const [model, definition] of Object.entries(module.schema)) {
|
|
110
|
-
const name = tableName(module, model);
|
|
111
|
-
const owner = owners.get(name);
|
|
112
|
-
if (owner !== void 0) problems.push(`${module.id}.${model}: table "${name}" is also declared by ${owner}`);
|
|
113
|
-
owners.set(name, `${module.id}.${model}`);
|
|
114
|
-
problems.push(...problemsOf(module, model, definition));
|
|
115
|
-
}
|
|
116
|
-
if (problems.length > 0) throw new DatabaseSchemaError(`Invalid database schema:\n- ${problems.join("\n- ")}`);
|
|
117
|
-
};
|
|
118
|
-
const indexesOf = (definition) => [...Object.entries(definition.indexes).map(([name, index]) => ({
|
|
119
|
-
name,
|
|
120
|
-
eq: [...index.eq],
|
|
121
|
-
sort: [...index.sort],
|
|
122
|
-
...index.unique ? { unique: true } : {}
|
|
123
|
-
})), ...Object.entries(definition.fields).flatMap(([name, field]) => field.unique ? [{
|
|
124
|
-
name,
|
|
125
|
-
eq: [name],
|
|
126
|
-
sort: [],
|
|
127
|
-
unique: true
|
|
128
|
-
}] : [])];
|
|
129
|
-
/** Validates the modules, then resolves them into physical tables with engine columns. */
|
|
130
|
-
const resolveSchema = (modules) => {
|
|
131
|
-
validateSchema(modules);
|
|
132
|
-
const references = [];
|
|
133
|
-
for (const module of modules) for (const [model, definition] of Object.entries(module.schema)) {
|
|
134
|
-
if (definition.kind !== "table") continue;
|
|
135
|
-
const table = tableName(module, model);
|
|
136
|
-
for (const [field, { references: to }] of Object.entries(definition.fields)) {
|
|
137
|
-
if (to === void 0) continue;
|
|
138
|
-
const { onDelete } = to;
|
|
139
|
-
const target = tableName(module, to.model);
|
|
140
|
-
const counter = onDelete === "none" ? {} : { counter: `_refs_${table}_${field}` };
|
|
141
|
-
references.push({
|
|
142
|
-
table,
|
|
143
|
-
field,
|
|
144
|
-
target,
|
|
145
|
-
onDelete,
|
|
146
|
-
...counter
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
const models = /* @__PURE__ */ new Map();
|
|
151
|
-
for (const module of modules) for (const [model, definition] of Object.entries(module.schema)) {
|
|
152
|
-
const name = tableName(module, model);
|
|
153
|
-
const referencedBy = references.filter(({ target }) => target === name);
|
|
154
|
-
const columns = Object.entries(definition.fields).map(([field, { type, required, maxLength, ascii }]) => ({
|
|
155
|
-
name: field,
|
|
156
|
-
type,
|
|
157
|
-
nullable: required === false,
|
|
158
|
-
...maxLength === void 0 ? {} : { maxLength },
|
|
159
|
-
...ascii ? { ascii } : {}
|
|
160
|
-
}));
|
|
161
|
-
if (definition.kind === "table") for (const [field, { type, multi }] of Object.entries(definition.derived)) columns.push({
|
|
162
|
-
name: field,
|
|
163
|
-
type,
|
|
164
|
-
nullable: true,
|
|
165
|
-
...multi ? { multi } : {}
|
|
166
|
-
});
|
|
167
|
-
else columns.push(integer(SHARD_COLUMN), ...[...definition.counters, ...definition.gauges].map((metric) => integer(metric)), ...definition.distinct.map((metric) => ({
|
|
168
|
-
name: metric,
|
|
169
|
-
type: "string",
|
|
170
|
-
nullable: true
|
|
171
|
-
})));
|
|
172
|
-
for (const { counter } of referencedBy) if (counter !== void 0) columns.push(integer(counter, true));
|
|
173
|
-
columns.push(integer(DATABASE_VERSION_COLUMN, true));
|
|
174
|
-
models.set(name, {
|
|
175
|
-
module: module.id,
|
|
176
|
-
model,
|
|
177
|
-
definition,
|
|
178
|
-
table: {
|
|
179
|
-
name,
|
|
180
|
-
columns,
|
|
181
|
-
key: definition.kind === "aggregate" ? [...definition.key, SHARD_COLUMN] : [...definition.key],
|
|
182
|
-
indexes: indexesOf(definition),
|
|
183
|
-
...physicalRetention(definition)
|
|
184
|
-
},
|
|
185
|
-
references: references.filter(({ table }) => table === name),
|
|
186
|
-
referencedBy,
|
|
187
|
-
roots: new Map(Object.entries(definition.indexes).flatMap(([index, { root }]) => root === void 0 ? [] : [[index, tableName(module, root.model)]]))
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
return {
|
|
191
|
-
models,
|
|
192
|
-
tables: [...models.values()].map(({ table }) => table)
|
|
193
|
-
};
|
|
194
|
-
};
|
|
195
|
-
//#endregion
|
|
196
|
-
export { MAX_SHARDS, SHARD_COLUMN, resolveSchema, validateSchema };
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
//#region src/database/retention.ts
|
|
2
|
-
const MINUTE_MS = 6e4;
|
|
3
|
-
const HOUR_MS = 60 * MINUTE_MS;
|
|
4
|
-
const DAY_MS = 24 * HOUR_MS;
|
|
5
|
-
/** A model's retention as its physical table carries it, which each adapter maps natively. */
|
|
6
|
-
const physicalRetention = ({ retention }) => retention === void 0 ? {} : { retention: {
|
|
7
|
-
column: retention.field,
|
|
8
|
-
ms: retention.days * DAY_MS
|
|
9
|
-
} };
|
|
10
|
-
/** Models in a reference or a rooted index, which an expired row's delete would break. */
|
|
11
|
-
const linkedModels = (schema) => Object.entries(schema).flatMap(([name, { fields, indexes }]) => [...Object.values(fields).map(({ references }) => references), ...Object.values(indexes).map(({ root }) => root)].flatMap((link) => link ? [name, link.model] : []));
|
|
12
|
-
/**
|
|
13
|
-
* What is wrong with a model's retention: it counts from an integer field,
|
|
14
|
-
* over whole days, and expired rows are deleted without cascades, counter
|
|
15
|
-
* moves, or root bumps, so the model is in no reference or rooted index.
|
|
16
|
-
*/
|
|
17
|
-
const retentionProblems = (schema, model) => {
|
|
18
|
-
const definition = schema[model];
|
|
19
|
-
if (definition.retention === void 0) return [];
|
|
20
|
-
const { field, days } = definition.retention;
|
|
21
|
-
const declared = definition.fields[field] ?? (definition.kind === "table" ? definition.derived[field] : void 0);
|
|
22
|
-
return [
|
|
23
|
-
...declared?.type !== "integer" || "multi" in declared && declared.multi === true ? [`retention field "${field}" is not an integer field`] : [],
|
|
24
|
-
...Number.isSafeInteger(days) && days >= 1 ? [] : ["retention days must be a whole number of at least 1"],
|
|
25
|
-
...linkedModels(schema).includes(model) ? ["a model with retention is in no reference or rooted index"] : []
|
|
26
|
-
];
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Rows a pass deletes from each table: one statement or two a table, so a
|
|
30
|
-
* pass stays well inside D1's 50 queries an invocation.
|
|
31
|
-
*/
|
|
32
|
-
const PASS_LIMIT = 500;
|
|
33
|
-
/** The lease row: when the next pass is due, in epoch ms. */
|
|
34
|
-
const LEASE_KEY = "retention.nextPassAt";
|
|
35
|
-
/**
|
|
36
|
-
* The adapter, pruning during its writes with no scheduler: once the lease
|
|
37
|
-
* row in `leaseTable` is due, the write that takes it first runs one bounded
|
|
38
|
-
* pass over the tables with retention, and other writers skip. The next pass is due in an hour, or in a minute while a pass still
|
|
39
|
-
* found a full batch of expired rows in some table. A backend that expires
|
|
40
|
-
* rows natively, or a schema without retention, gets its adapter back.
|
|
41
|
-
*/
|
|
42
|
-
const pruneDuringWrites = (adapter, tables, { leaseTable: table, now }) => {
|
|
43
|
-
const expiring = tables.filter(({ retention }) => retention !== void 0);
|
|
44
|
-
if (adapter.prune === void 0 || expiring.length === 0) return adapter;
|
|
45
|
-
const key = [LEASE_KEY];
|
|
46
|
-
let checkAt = 0;
|
|
47
|
-
const lease = async (row, due) => {
|
|
48
|
-
const value = String(due);
|
|
49
|
-
const guard = { v: row === null ? -1 : Number(row._v) };
|
|
50
|
-
const next = {
|
|
51
|
-
key: LEASE_KEY,
|
|
52
|
-
value,
|
|
53
|
-
_v: guard.v + 1
|
|
54
|
-
};
|
|
55
|
-
const op = row === null ? {
|
|
56
|
-
type: "insert",
|
|
57
|
-
table,
|
|
58
|
-
row: next
|
|
59
|
-
} : {
|
|
60
|
-
type: "patch",
|
|
61
|
-
table,
|
|
62
|
-
key,
|
|
63
|
-
set: { value },
|
|
64
|
-
guard,
|
|
65
|
-
previous: row
|
|
66
|
-
};
|
|
67
|
-
return (await adapter.write([op])).ok ? next : null;
|
|
68
|
-
};
|
|
69
|
-
const pass = async () => {
|
|
70
|
-
const at = now();
|
|
71
|
-
if (at < checkAt) return;
|
|
72
|
-
checkAt = at + MINUTE_MS;
|
|
73
|
-
const [row = null] = await adapter.get(table, [key]);
|
|
74
|
-
checkAt = row === null ? at : Number(row.value);
|
|
75
|
-
if (checkAt > at) return;
|
|
76
|
-
const held = await lease(row, at + HOUR_MS);
|
|
77
|
-
if (held === null) return;
|
|
78
|
-
checkAt = at + HOUR_MS;
|
|
79
|
-
const deleted = [];
|
|
80
|
-
for (const t of expiring) deleted.push(await adapter.prune(t, at - t.retention.ms, PASS_LIMIT));
|
|
81
|
-
if (deleted.includes(PASS_LIMIT) && await lease(held, at + MINUTE_MS) !== null) checkAt = at + MINUTE_MS;
|
|
82
|
-
};
|
|
83
|
-
const warn = (error) => console.warn("[hot-updater] Pruning expired rows failed.", error);
|
|
84
|
-
return Object.assign(Object.create(adapter), { async write(ops) {
|
|
85
|
-
await pass().catch(warn);
|
|
86
|
-
return adapter.write(ops);
|
|
87
|
-
} });
|
|
88
|
-
};
|
|
89
|
-
//#endregion
|
|
90
|
-
exports.physicalRetention = physicalRetention;
|
|
91
|
-
exports.pruneDuringWrites = pruneDuringWrites;
|
|
92
|
-
exports.retentionProblems = retentionProblems;
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
//#region src/database/retention.ts
|
|
2
|
-
const MINUTE_MS = 6e4;
|
|
3
|
-
const HOUR_MS = 60 * MINUTE_MS;
|
|
4
|
-
const DAY_MS = 24 * HOUR_MS;
|
|
5
|
-
/** A model's retention as its physical table carries it, which each adapter maps natively. */
|
|
6
|
-
const physicalRetention = ({ retention }) => retention === void 0 ? {} : { retention: {
|
|
7
|
-
column: retention.field,
|
|
8
|
-
ms: retention.days * DAY_MS
|
|
9
|
-
} };
|
|
10
|
-
/** Models in a reference or a rooted index, which an expired row's delete would break. */
|
|
11
|
-
const linkedModels = (schema) => Object.entries(schema).flatMap(([name, { fields, indexes }]) => [...Object.values(fields).map(({ references }) => references), ...Object.values(indexes).map(({ root }) => root)].flatMap((link) => link ? [name, link.model] : []));
|
|
12
|
-
/**
|
|
13
|
-
* What is wrong with a model's retention: it counts from an integer field,
|
|
14
|
-
* over whole days, and expired rows are deleted without cascades, counter
|
|
15
|
-
* moves, or root bumps, so the model is in no reference or rooted index.
|
|
16
|
-
*/
|
|
17
|
-
const retentionProblems = (schema, model) => {
|
|
18
|
-
const definition = schema[model];
|
|
19
|
-
if (definition.retention === void 0) return [];
|
|
20
|
-
const { field, days } = definition.retention;
|
|
21
|
-
const declared = definition.fields[field] ?? (definition.kind === "table" ? definition.derived[field] : void 0);
|
|
22
|
-
return [
|
|
23
|
-
...declared?.type !== "integer" || "multi" in declared && declared.multi === true ? [`retention field "${field}" is not an integer field`] : [],
|
|
24
|
-
...Number.isSafeInteger(days) && days >= 1 ? [] : ["retention days must be a whole number of at least 1"],
|
|
25
|
-
...linkedModels(schema).includes(model) ? ["a model with retention is in no reference or rooted index"] : []
|
|
26
|
-
];
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Rows a pass deletes from each table: one statement or two a table, so a
|
|
30
|
-
* pass stays well inside D1's 50 queries an invocation.
|
|
31
|
-
*/
|
|
32
|
-
const PASS_LIMIT = 500;
|
|
33
|
-
/** The lease row: when the next pass is due, in epoch ms. */
|
|
34
|
-
const LEASE_KEY = "retention.nextPassAt";
|
|
35
|
-
/**
|
|
36
|
-
* The adapter, pruning during its writes with no scheduler: once the lease
|
|
37
|
-
* row in `leaseTable` is due, the write that takes it first runs one bounded
|
|
38
|
-
* pass over the tables with retention, and other writers skip. The next pass is due in an hour, or in a minute while a pass still
|
|
39
|
-
* found a full batch of expired rows in some table. A backend that expires
|
|
40
|
-
* rows natively, or a schema without retention, gets its adapter back.
|
|
41
|
-
*/
|
|
42
|
-
const pruneDuringWrites = (adapter, tables, { leaseTable: table, now }) => {
|
|
43
|
-
const expiring = tables.filter(({ retention }) => retention !== void 0);
|
|
44
|
-
if (adapter.prune === void 0 || expiring.length === 0) return adapter;
|
|
45
|
-
const key = [LEASE_KEY];
|
|
46
|
-
let checkAt = 0;
|
|
47
|
-
const lease = async (row, due) => {
|
|
48
|
-
const value = String(due);
|
|
49
|
-
const guard = { v: row === null ? -1 : Number(row._v) };
|
|
50
|
-
const next = {
|
|
51
|
-
key: LEASE_KEY,
|
|
52
|
-
value,
|
|
53
|
-
_v: guard.v + 1
|
|
54
|
-
};
|
|
55
|
-
const op = row === null ? {
|
|
56
|
-
type: "insert",
|
|
57
|
-
table,
|
|
58
|
-
row: next
|
|
59
|
-
} : {
|
|
60
|
-
type: "patch",
|
|
61
|
-
table,
|
|
62
|
-
key,
|
|
63
|
-
set: { value },
|
|
64
|
-
guard,
|
|
65
|
-
previous: row
|
|
66
|
-
};
|
|
67
|
-
return (await adapter.write([op])).ok ? next : null;
|
|
68
|
-
};
|
|
69
|
-
const pass = async () => {
|
|
70
|
-
const at = now();
|
|
71
|
-
if (at < checkAt) return;
|
|
72
|
-
checkAt = at + MINUTE_MS;
|
|
73
|
-
const [row = null] = await adapter.get(table, [key]);
|
|
74
|
-
checkAt = row === null ? at : Number(row.value);
|
|
75
|
-
if (checkAt > at) return;
|
|
76
|
-
const held = await lease(row, at + HOUR_MS);
|
|
77
|
-
if (held === null) return;
|
|
78
|
-
checkAt = at + HOUR_MS;
|
|
79
|
-
const deleted = [];
|
|
80
|
-
for (const t of expiring) deleted.push(await adapter.prune(t, at - t.retention.ms, PASS_LIMIT));
|
|
81
|
-
if (deleted.includes(PASS_LIMIT) && await lease(held, at + MINUTE_MS) !== null) checkAt = at + MINUTE_MS;
|
|
82
|
-
};
|
|
83
|
-
const warn = (error) => console.warn("[hot-updater] Pruning expired rows failed.", error);
|
|
84
|
-
return Object.assign(Object.create(adapter), { async write(ops) {
|
|
85
|
-
await pass().catch(warn);
|
|
86
|
-
return adapter.write(ops);
|
|
87
|
-
} });
|
|
88
|
-
};
|
|
89
|
-
//#endregion
|
|
90
|
-
export { physicalRetention, pruneDuringWrites, retentionProblems };
|
package/dist/database/schema.cjs
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
//#region src/database/schema.ts
|
|
2
|
-
const defineTable = (fields, options) => ({
|
|
3
|
-
kind: "table",
|
|
4
|
-
fields,
|
|
5
|
-
key: options.key,
|
|
6
|
-
derived: options.derived ?? {},
|
|
7
|
-
indexes: options.indexes ?? {},
|
|
8
|
-
...options.retention === void 0 ? {} : { retention: options.retention }
|
|
9
|
-
});
|
|
10
|
-
const defineAggregate = (fields, options) => ({
|
|
11
|
-
kind: "aggregate",
|
|
12
|
-
fields,
|
|
13
|
-
key: options.key,
|
|
14
|
-
counters: options.counters ?? [],
|
|
15
|
-
gauges: options.gauges ?? [],
|
|
16
|
-
distinct: options.distinct ?? [],
|
|
17
|
-
shards: options.shards ?? 1,
|
|
18
|
-
indexes: options.indexes ?? {},
|
|
19
|
-
...options.batched ? { batched: true } : {},
|
|
20
|
-
...options.retention === void 0 ? {} : { retention: options.retention }
|
|
21
|
-
});
|
|
22
|
-
//#endregion
|
|
23
|
-
exports.defineAggregate = defineAggregate;
|
|
24
|
-
exports.defineTable = defineTable;
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { AggregateShape, FieldDefinition, FieldReference, FieldType, IndexDefinition, ReferenceAction, TableShape } from "./definitions.cjs";
|
|
2
|
-
import { DatabaseJson } from "@hot-updater/plugin-core/internal";
|
|
3
|
-
//#region src/database/schema.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* How long a model keeps its rows: `days` past the epoch milliseconds in
|
|
6
|
-
* `field`, an integer field (a table's derived one too, where null keeps
|
|
7
|
-
* the row). Expired rows are deleted without cascades, so a model with
|
|
8
|
-
* retention is in no reference and no rooted index.
|
|
9
|
-
*/
|
|
10
|
-
interface RetentionDefinition<TField extends string = string> {
|
|
11
|
-
readonly field: TField;
|
|
12
|
-
readonly days: number;
|
|
13
|
-
}
|
|
14
|
-
type FieldValue<TType extends FieldType> = TType extends "string" ? string : TType extends "integer" | "number" ? number : TType extends "boolean" ? boolean : DatabaseJson;
|
|
15
|
-
type Fields = Readonly<Record<string, FieldDefinition>>;
|
|
16
|
-
type RowOf<TFields extends Fields> = { -readonly [K in keyof TFields]: TFields[K] extends FieldDefinition<infer TType> ? TFields[K] extends {
|
|
17
|
-
readonly required: false;
|
|
18
|
-
} ? FieldValue<TType> | null : FieldValue<TType> : never; };
|
|
19
|
-
/** Computed on every write and stored as a real column. */
|
|
20
|
-
interface DerivedDefinition<TRow = never, TType extends FieldType = FieldType> {
|
|
21
|
-
readonly type: TType;
|
|
22
|
-
/** Up to 16 values; the row is indexed once per value. */
|
|
23
|
-
readonly multi?: true;
|
|
24
|
-
/** Null, or an empty list, leaves the row out of indexes on this field. */
|
|
25
|
-
compute(row: TRow): FieldValue<TType> | null | readonly FieldValue<TType>[];
|
|
26
|
-
}
|
|
27
|
-
type DerivedTypes = Readonly<Record<string, FieldType>>;
|
|
28
|
-
/** Derived fields over a table's row, by name. */
|
|
29
|
-
type DerivedFields<TFields extends Fields, TDerived extends DerivedTypes> = { readonly [K in keyof TDerived]: DerivedDefinition<RowOf<TFields>, TDerived[K]>; };
|
|
30
|
-
type Indexes = Readonly<Record<string, IndexDefinition>>;
|
|
31
|
-
/** The integer fields, declared or derived, that retention can count from. */
|
|
32
|
-
type IntegerFields<TFields extends Fields, TDerived extends DerivedTypes> = { [K in keyof TFields]: TFields[K] extends {
|
|
33
|
-
readonly type: "integer";
|
|
34
|
-
} ? K : never; }[keyof TFields] | { [K in keyof TDerived]: TDerived[K] extends "integer" ? K : never; }[keyof TDerived];
|
|
35
|
-
type MissingFields<TIndex, TNames extends string> = TIndex extends {
|
|
36
|
-
readonly eq: readonly (infer TEq)[];
|
|
37
|
-
readonly sort: readonly (infer TSort)[];
|
|
38
|
-
} ? Exclude<TEq | TSort, TNames> : never;
|
|
39
|
-
/** Maps an index to an error message when it names an undeclared field. */
|
|
40
|
-
type CheckIndex<TName extends PropertyKey, TIndex, TNames extends string> = [MissingFields<TIndex, TNames>] extends [never] ? TIndex : `Index "${TName & string}" names undeclared field "${MissingFields<TIndex, TNames> & string}"`;
|
|
41
|
-
type CheckIndexes<TIndexes, TNames extends string> = { readonly [K in keyof TIndexes]: CheckIndex<K, TIndexes[K], TNames>; };
|
|
42
|
-
interface TableDefinition<TFields extends Fields = Fields, TDerived extends DerivedTypes = DerivedTypes, TIndexes extends Indexes = Indexes, TKey extends readonly (keyof TFields & string)[] = readonly (keyof TFields & string)[]> extends TableShape {
|
|
43
|
-
readonly kind: "table";
|
|
44
|
-
readonly fields: TFields;
|
|
45
|
-
readonly key: TKey;
|
|
46
|
-
readonly derived: DerivedFields<TFields, TDerived>;
|
|
47
|
-
readonly indexes: TIndexes;
|
|
48
|
-
}
|
|
49
|
-
declare const defineTable: <const TFields extends Fields, const TKey extends readonly (keyof TFields & string)[], const TDerived extends DerivedTypes = {}, const TIndexes extends Indexes = {}>(fields: TFields, options: {
|
|
50
|
-
readonly key: TKey;
|
|
51
|
-
readonly derived?: DerivedFields<TFields, TDerived>;
|
|
52
|
-
readonly indexes?: TIndexes & CheckIndexes<TIndexes, (keyof TFields | keyof TDerived) & string>;
|
|
53
|
-
/** Rows expire `days` after the epoch milliseconds in `field`. */
|
|
54
|
-
readonly retention?: RetentionDefinition<IntegerFields<TFields, TDerived> & string>;
|
|
55
|
-
}) => TableDefinition<TFields, TDerived, TIndexes, TKey>;
|
|
56
|
-
interface AggregateDefinition<TFields extends Fields = Fields, TMetric extends string = string, TIndexes extends Indexes = Indexes, TSketch extends string = string, TKey extends readonly (keyof TFields & string)[] = readonly (keyof TFields & string)[]> extends AggregateShape {
|
|
57
|
-
readonly kind: "aggregate";
|
|
58
|
-
readonly fields: TFields;
|
|
59
|
-
readonly key: TKey;
|
|
60
|
-
readonly counters: readonly TMetric[];
|
|
61
|
-
readonly gauges: readonly TMetric[];
|
|
62
|
-
readonly distinct: readonly TSketch[];
|
|
63
|
-
readonly indexes: TIndexes;
|
|
64
|
-
/**
|
|
65
|
-
* On a database that batches aggregates, changes apply after their
|
|
66
|
-
* transaction commits, in one write per row with other transactions'
|
|
67
|
-
* changes, so reads may lag them. Elsewhere they commit with it.
|
|
68
|
-
*/
|
|
69
|
-
readonly batched?: true;
|
|
70
|
-
}
|
|
71
|
-
declare const defineAggregate: <const TFields extends Fields, const TKey extends readonly (keyof TFields & string)[], const TMetric extends string = never, const TIndexes extends Indexes = {}, const TSketch extends string = never>(fields: TFields, options: {
|
|
72
|
-
readonly key: TKey;
|
|
73
|
-
readonly counters?: readonly TMetric[];
|
|
74
|
-
readonly gauges?: readonly TMetric[];
|
|
75
|
-
readonly distinct?: readonly TSketch[];
|
|
76
|
-
readonly shards?: number;
|
|
77
|
-
readonly indexes?: TIndexes & CheckIndexes<TIndexes, keyof TFields & string>;
|
|
78
|
-
readonly batched?: true;
|
|
79
|
-
/**
|
|
80
|
-
* Rows expire `days` after the epoch milliseconds in `field`, an
|
|
81
|
-
* identity field such as a bucket's start; a change to a row already
|
|
82
|
-
* past it is dropped, so a late gauge decrement never goes below zero.
|
|
83
|
-
*/
|
|
84
|
-
readonly retention?: RetentionDefinition<IntegerFields<TFields, {}> & string>;
|
|
85
|
-
}) => AggregateDefinition<TFields, TMetric, TIndexes, TSketch, TKey>;
|
|
86
|
-
type ModelDefinition = TableDefinition | AggregateDefinition;
|
|
87
|
-
/** A module's models by name: core, or one plugin. */
|
|
88
|
-
type ModuleSchema = Readonly<Record<string, ModelDefinition>>;
|
|
89
|
-
//#endregion
|
|
90
|
-
export { AggregateDefinition, CheckIndex, DerivedDefinition, DerivedFields, type FieldDefinition, type FieldReference, type FieldType, FieldValue, type IndexDefinition, ModelDefinition, ModuleSchema, type ReferenceAction, RetentionDefinition, RowOf, TableDefinition, defineAggregate, defineTable };
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { AggregateShape, FieldDefinition, FieldReference, FieldType, IndexDefinition, ReferenceAction, TableShape } from "./definitions.mjs";
|
|
2
|
-
import { DatabaseJson } from "@hot-updater/plugin-core/internal";
|
|
3
|
-
//#region src/database/schema.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* How long a model keeps its rows: `days` past the epoch milliseconds in
|
|
6
|
-
* `field`, an integer field (a table's derived one too, where null keeps
|
|
7
|
-
* the row). Expired rows are deleted without cascades, so a model with
|
|
8
|
-
* retention is in no reference and no rooted index.
|
|
9
|
-
*/
|
|
10
|
-
interface RetentionDefinition<TField extends string = string> {
|
|
11
|
-
readonly field: TField;
|
|
12
|
-
readonly days: number;
|
|
13
|
-
}
|
|
14
|
-
type FieldValue<TType extends FieldType> = TType extends "string" ? string : TType extends "integer" | "number" ? number : TType extends "boolean" ? boolean : DatabaseJson;
|
|
15
|
-
type Fields = Readonly<Record<string, FieldDefinition>>;
|
|
16
|
-
type RowOf<TFields extends Fields> = { -readonly [K in keyof TFields]: TFields[K] extends FieldDefinition<infer TType> ? TFields[K] extends {
|
|
17
|
-
readonly required: false;
|
|
18
|
-
} ? FieldValue<TType> | null : FieldValue<TType> : never; };
|
|
19
|
-
/** Computed on every write and stored as a real column. */
|
|
20
|
-
interface DerivedDefinition<TRow = never, TType extends FieldType = FieldType> {
|
|
21
|
-
readonly type: TType;
|
|
22
|
-
/** Up to 16 values; the row is indexed once per value. */
|
|
23
|
-
readonly multi?: true;
|
|
24
|
-
/** Null, or an empty list, leaves the row out of indexes on this field. */
|
|
25
|
-
compute(row: TRow): FieldValue<TType> | null | readonly FieldValue<TType>[];
|
|
26
|
-
}
|
|
27
|
-
type DerivedTypes = Readonly<Record<string, FieldType>>;
|
|
28
|
-
/** Derived fields over a table's row, by name. */
|
|
29
|
-
type DerivedFields<TFields extends Fields, TDerived extends DerivedTypes> = { readonly [K in keyof TDerived]: DerivedDefinition<RowOf<TFields>, TDerived[K]>; };
|
|
30
|
-
type Indexes = Readonly<Record<string, IndexDefinition>>;
|
|
31
|
-
/** The integer fields, declared or derived, that retention can count from. */
|
|
32
|
-
type IntegerFields<TFields extends Fields, TDerived extends DerivedTypes> = { [K in keyof TFields]: TFields[K] extends {
|
|
33
|
-
readonly type: "integer";
|
|
34
|
-
} ? K : never; }[keyof TFields] | { [K in keyof TDerived]: TDerived[K] extends "integer" ? K : never; }[keyof TDerived];
|
|
35
|
-
type MissingFields<TIndex, TNames extends string> = TIndex extends {
|
|
36
|
-
readonly eq: readonly (infer TEq)[];
|
|
37
|
-
readonly sort: readonly (infer TSort)[];
|
|
38
|
-
} ? Exclude<TEq | TSort, TNames> : never;
|
|
39
|
-
/** Maps an index to an error message when it names an undeclared field. */
|
|
40
|
-
type CheckIndex<TName extends PropertyKey, TIndex, TNames extends string> = [MissingFields<TIndex, TNames>] extends [never] ? TIndex : `Index "${TName & string}" names undeclared field "${MissingFields<TIndex, TNames> & string}"`;
|
|
41
|
-
type CheckIndexes<TIndexes, TNames extends string> = { readonly [K in keyof TIndexes]: CheckIndex<K, TIndexes[K], TNames>; };
|
|
42
|
-
interface TableDefinition<TFields extends Fields = Fields, TDerived extends DerivedTypes = DerivedTypes, TIndexes extends Indexes = Indexes, TKey extends readonly (keyof TFields & string)[] = readonly (keyof TFields & string)[]> extends TableShape {
|
|
43
|
-
readonly kind: "table";
|
|
44
|
-
readonly fields: TFields;
|
|
45
|
-
readonly key: TKey;
|
|
46
|
-
readonly derived: DerivedFields<TFields, TDerived>;
|
|
47
|
-
readonly indexes: TIndexes;
|
|
48
|
-
}
|
|
49
|
-
declare const defineTable: <const TFields extends Fields, const TKey extends readonly (keyof TFields & string)[], const TDerived extends DerivedTypes = {}, const TIndexes extends Indexes = {}>(fields: TFields, options: {
|
|
50
|
-
readonly key: TKey;
|
|
51
|
-
readonly derived?: DerivedFields<TFields, TDerived>;
|
|
52
|
-
readonly indexes?: TIndexes & CheckIndexes<TIndexes, (keyof TFields | keyof TDerived) & string>;
|
|
53
|
-
/** Rows expire `days` after the epoch milliseconds in `field`. */
|
|
54
|
-
readonly retention?: RetentionDefinition<IntegerFields<TFields, TDerived> & string>;
|
|
55
|
-
}) => TableDefinition<TFields, TDerived, TIndexes, TKey>;
|
|
56
|
-
interface AggregateDefinition<TFields extends Fields = Fields, TMetric extends string = string, TIndexes extends Indexes = Indexes, TSketch extends string = string, TKey extends readonly (keyof TFields & string)[] = readonly (keyof TFields & string)[]> extends AggregateShape {
|
|
57
|
-
readonly kind: "aggregate";
|
|
58
|
-
readonly fields: TFields;
|
|
59
|
-
readonly key: TKey;
|
|
60
|
-
readonly counters: readonly TMetric[];
|
|
61
|
-
readonly gauges: readonly TMetric[];
|
|
62
|
-
readonly distinct: readonly TSketch[];
|
|
63
|
-
readonly indexes: TIndexes;
|
|
64
|
-
/**
|
|
65
|
-
* On a database that batches aggregates, changes apply after their
|
|
66
|
-
* transaction commits, in one write per row with other transactions'
|
|
67
|
-
* changes, so reads may lag them. Elsewhere they commit with it.
|
|
68
|
-
*/
|
|
69
|
-
readonly batched?: true;
|
|
70
|
-
}
|
|
71
|
-
declare const defineAggregate: <const TFields extends Fields, const TKey extends readonly (keyof TFields & string)[], const TMetric extends string = never, const TIndexes extends Indexes = {}, const TSketch extends string = never>(fields: TFields, options: {
|
|
72
|
-
readonly key: TKey;
|
|
73
|
-
readonly counters?: readonly TMetric[];
|
|
74
|
-
readonly gauges?: readonly TMetric[];
|
|
75
|
-
readonly distinct?: readonly TSketch[];
|
|
76
|
-
readonly shards?: number;
|
|
77
|
-
readonly indexes?: TIndexes & CheckIndexes<TIndexes, keyof TFields & string>;
|
|
78
|
-
readonly batched?: true;
|
|
79
|
-
/**
|
|
80
|
-
* Rows expire `days` after the epoch milliseconds in `field`, an
|
|
81
|
-
* identity field such as a bucket's start; a change to a row already
|
|
82
|
-
* past it is dropped, so a late gauge decrement never goes below zero.
|
|
83
|
-
*/
|
|
84
|
-
readonly retention?: RetentionDefinition<IntegerFields<TFields, {}> & string>;
|
|
85
|
-
}) => AggregateDefinition<TFields, TMetric, TIndexes, TSketch, TKey>;
|
|
86
|
-
type ModelDefinition = TableDefinition | AggregateDefinition;
|
|
87
|
-
/** A module's models by name: core, or one plugin. */
|
|
88
|
-
type ModuleSchema = Readonly<Record<string, ModelDefinition>>;
|
|
89
|
-
//#endregion
|
|
90
|
-
export { AggregateDefinition, CheckIndex, DerivedDefinition, DerivedFields, type FieldDefinition, type FieldReference, type FieldType, FieldValue, type IndexDefinition, ModelDefinition, ModuleSchema, type ReferenceAction, RetentionDefinition, RowOf, TableDefinition, defineAggregate, defineTable };
|
package/dist/database/schema.mjs
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
//#region src/database/schema.ts
|
|
2
|
-
const defineTable = (fields, options) => ({
|
|
3
|
-
kind: "table",
|
|
4
|
-
fields,
|
|
5
|
-
key: options.key,
|
|
6
|
-
derived: options.derived ?? {},
|
|
7
|
-
indexes: options.indexes ?? {},
|
|
8
|
-
...options.retention === void 0 ? {} : { retention: options.retention }
|
|
9
|
-
});
|
|
10
|
-
const defineAggregate = (fields, options) => ({
|
|
11
|
-
kind: "aggregate",
|
|
12
|
-
fields,
|
|
13
|
-
key: options.key,
|
|
14
|
-
counters: options.counters ?? [],
|
|
15
|
-
gauges: options.gauges ?? [],
|
|
16
|
-
distinct: options.distinct ?? [],
|
|
17
|
-
shards: options.shards ?? 1,
|
|
18
|
-
indexes: options.indexes ?? {},
|
|
19
|
-
...options.batched ? { batched: true } : {},
|
|
20
|
-
...options.retention === void 0 ? {} : { retention: options.retention }
|
|
21
|
-
});
|
|
22
|
-
//#endregion
|
|
23
|
-
export { defineAggregate, defineTable };
|