@adcp/sdk 12.0.0 → 12.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/adapters/content-standards-adapter.mjs +0 -6
- package/dist/lib/adapters/content-standards-adapter.mjs.map +1 -1
- package/dist/lib/adapters/derived-account-store.mjs +0 -6
- package/dist/lib/adapters/derived-account-store.mjs.map +1 -1
- package/dist/lib/adapters/governance-adapter.mjs +0 -6
- package/dist/lib/adapters/governance-adapter.mjs.map +1 -1
- package/dist/lib/adapters/implicit-account-store.mjs +0 -6
- package/dist/lib/adapters/implicit-account-store.mjs.map +1 -1
- package/dist/lib/adapters/index.mjs +0 -6
- package/dist/lib/adapters/index.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/get_products.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/get_products.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/index.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/index.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/types.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs.map +1 -1
- package/dist/lib/adapters/oauth-passthrough-resolver.mjs +0 -6
- package/dist/lib/adapters/oauth-passthrough-resolver.mjs.map +1 -1
- package/dist/lib/adapters/property-list-adapter.mjs +0 -6
- package/dist/lib/adapters/property-list-adapter.mjs.map +1 -1
- package/dist/lib/adapters/roster-account-store.mjs +0 -6
- package/dist/lib/adapters/roster-account-store.mjs.map +1 -1
- package/dist/lib/adapters/si-session-manager.mjs +0 -6
- package/dist/lib/adapters/si-session-manager.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/brand-fields.mjs +0 -6
- package/dist/lib/adapters/version/3.0/brand-fields.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/get-products.mjs +0 -6
- package/dist/lib/adapters/version/3.0/get-products.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/index.mjs +0 -6
- package/dist/lib/adapters/version/3.0/index.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/sync-accounts.mjs +0 -6
- package/dist/lib/adapters/version/3.0/sync-accounts.mjs.map +1 -1
- package/dist/lib/adapters/version/index.mjs +0 -6
- package/dist/lib/adapters/version/index.mjs.map +1 -1
- package/dist/lib/adapters/version/types.mjs +0 -6
- package/dist/lib/advanced.mjs +0 -6
- package/dist/lib/advanced.mjs.map +1 -1
- package/dist/lib/agents/index.generated.mjs +0 -6
- package/dist/lib/agents/index.generated.mjs.map +1 -1
- package/dist/lib/auth/index.mjs +0 -6
- package/dist/lib/auth/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs +0 -6
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs.map +1 -1
- package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs +0 -6
- package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs.map +1 -1
- package/dist/lib/auth/oauth/MCPOAuthProvider.mjs +0 -6
- package/dist/lib/auth/oauth/MCPOAuthProvider.mjs.map +1 -1
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs +0 -6
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs.map +1 -1
- package/dist/lib/auth/oauth/authorization-required.mjs +0 -6
- package/dist/lib/auth/oauth/authorization-required.mjs.map +1 -1
- package/dist/lib/auth/oauth/diagnose.mjs +0 -6
- package/dist/lib/auth/oauth/diagnose.mjs.map +1 -1
- package/dist/lib/auth/oauth/diagnostics.mjs +0 -6
- package/dist/lib/auth/oauth/diagnostics.mjs.map +1 -1
- package/dist/lib/auth/oauth/discovery.mjs +0 -6
- package/dist/lib/auth/oauth/discovery.mjs.map +1 -1
- package/dist/lib/auth/oauth/file-storage.mjs +0 -6
- package/dist/lib/auth/oauth/file-storage.mjs.map +1 -1
- package/dist/lib/auth/oauth/index.mjs +0 -6
- package/dist/lib/auth/oauth/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/secret-resolver.mjs +0 -6
- package/dist/lib/auth/oauth/secret-resolver.mjs.map +1 -1
- package/dist/lib/auth/oauth/storage-registry.mjs +0 -6
- package/dist/lib/auth/oauth/storage-registry.mjs.map +1 -1
- package/dist/lib/auth/oauth/types.mjs +0 -6
- package/dist/lib/auth/oauth/types.mjs.map +1 -1
- package/dist/lib/auth/oauth/web-flow.mjs +0 -6
- package/dist/lib/auth/oauth/web-flow.mjs.map +1 -1
- package/dist/lib/brand/index.mjs +0 -6
- package/dist/lib/brand/index.mjs.map +1 -1
- package/dist/lib/canonical-references/index.mjs +6 -7
- package/dist/lib/canonical-references/index.mjs.map +1 -1
- package/dist/lib/client/index.mjs +0 -6
- package/dist/lib/client/index.mjs.map +1 -1
- package/dist/lib/compliance/index.mjs +0 -6
- package/dist/lib/compliance/index.mjs.map +1 -1
- package/dist/lib/compliance-fixtures/index.mjs +0 -6
- package/dist/lib/compliance-fixtures/index.mjs.map +1 -1
- package/dist/lib/compliance-fixtures/test-authorization-server.mjs +0 -6
- package/dist/lib/compliance-fixtures/test-authorization-server.mjs.map +1 -1
- package/dist/lib/conformance/index.mjs +0 -6
- package/dist/lib/conformance/index.mjs.map +1 -1
- package/dist/lib/conformance/invariants/uniformError.mjs +0 -6
- package/dist/lib/conformance/invariants/uniformError.mjs.map +1 -1
- package/dist/lib/conformance/invariants/uniformErrorComparator.mjs +0 -6
- package/dist/lib/conformance/invariants/uniformErrorComparator.mjs.map +1 -1
- package/dist/lib/conformance/oracle.mjs +0 -6
- package/dist/lib/conformance/oracle.mjs.map +1 -1
- package/dist/lib/conformance/runConformance.mjs +0 -6
- package/dist/lib/conformance/runConformance.mjs.map +1 -1
- package/dist/lib/conformance/runners.mjs +0 -6
- package/dist/lib/conformance/runners.mjs.map +1 -1
- package/dist/lib/conformance/schemaArbitrary.mjs +0 -6
- package/dist/lib/conformance/schemaArbitrary.mjs.map +1 -1
- package/dist/lib/conformance/schemaLoader.mjs +5 -6
- package/dist/lib/conformance/schemaLoader.mjs.map +1 -1
- package/dist/lib/conformance/seeder.mjs +0 -6
- package/dist/lib/conformance/seeder.mjs.map +1 -1
- package/dist/lib/conformance/types.mjs +0 -6
- package/dist/lib/conformance/types.mjs.map +1 -1
- package/dist/lib/conformance/webhook.mjs +0 -6
- package/dist/lib/conformance/webhook.mjs.map +1 -1
- package/dist/lib/core/ADCPMultiAgentClient.mjs +0 -6
- package/dist/lib/core/ADCPMultiAgentClient.mjs.map +1 -1
- package/dist/lib/core/AgentClient.mjs +0 -6
- package/dist/lib/core/AgentClient.mjs.map +1 -1
- package/dist/lib/core/AsyncHandler.mjs +0 -6
- package/dist/lib/core/AsyncHandler.mjs.map +1 -1
- package/dist/lib/core/ConfigurationManager.mjs +0 -6
- package/dist/lib/core/ConfigurationManager.mjs.map +1 -1
- package/dist/lib/core/ConversationTypes.mjs +0 -6
- package/dist/lib/core/CreativeAgentClient.mjs +0 -6
- package/dist/lib/core/CreativeAgentClient.mjs.map +1 -1
- package/dist/lib/core/GovernanceMiddleware.mjs +0 -6
- package/dist/lib/core/GovernanceMiddleware.mjs.map +1 -1
- package/dist/lib/core/GovernanceTypes.mjs +0 -6
- package/dist/lib/core/GovernanceTypes.mjs.map +1 -1
- package/dist/lib/core/ProtocolResponseParser.mjs +0 -6
- package/dist/lib/core/ProtocolResponseParser.mjs.map +1 -1
- package/dist/lib/core/ResponseValidator.mjs +0 -6
- package/dist/lib/core/ResponseValidator.mjs.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +0 -6
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/core/TaskEventTypes.mjs +0 -6
- package/dist/lib/core/TaskEventTypes.mjs.map +1 -1
- package/dist/lib/core/TaskExecutor.mjs +0 -6
- package/dist/lib/core/TaskExecutor.mjs.map +1 -1
- package/dist/lib/core/match.mjs +0 -6
- package/dist/lib/core/match.mjs.map +1 -1
- package/dist/lib/core/task-status.mjs +0 -6
- package/dist/lib/core/task-status.mjs.map +1 -1
- package/dist/lib/core/webhook-url.mjs +0 -6
- package/dist/lib/core/webhook-url.mjs.map +1 -1
- package/dist/lib/discovery/adagents-redirects.mjs +0 -6
- package/dist/lib/discovery/adagents-redirects.mjs.map +1 -1
- package/dist/lib/discovery/agent-directory.mjs +0 -6
- package/dist/lib/discovery/agent-directory.mjs.map +1 -1
- package/dist/lib/discovery/inline-publisher-properties.mjs +0 -6
- package/dist/lib/discovery/inline-publisher-properties.mjs.map +1 -1
- package/dist/lib/discovery/network-consistency-checker.mjs +0 -6
- package/dist/lib/discovery/network-consistency-checker.mjs.map +1 -1
- package/dist/lib/discovery/property-crawler.mjs +0 -6
- package/dist/lib/discovery/property-crawler.mjs.map +1 -1
- package/dist/lib/discovery/property-index.mjs +0 -6
- package/dist/lib/discovery/property-index.mjs.map +1 -1
- package/dist/lib/discovery/publisher-property-selector.mjs +0 -6
- package/dist/lib/discovery/publisher-property-selector.mjs.map +1 -1
- package/dist/lib/discovery/resolve-agent-properties.mjs +0 -6
- package/dist/lib/discovery/resolve-agent-properties.mjs.map +1 -1
- package/dist/lib/discovery/types.mjs +0 -6
- package/dist/lib/discovery/validate-adagents.mjs +0 -6
- package/dist/lib/discovery/validate-adagents.mjs.map +1 -1
- package/dist/lib/enums.mjs +0 -6
- package/dist/lib/enums.mjs.map +1 -1
- package/dist/lib/errors/index.mjs +0 -6
- package/dist/lib/errors/index.mjs.map +1 -1
- package/dist/lib/express-mcp/index.mjs +0 -6
- package/dist/lib/express-mcp/index.mjs.map +1 -1
- package/dist/lib/governance/index.mjs +0 -6
- package/dist/lib/governance/index.mjs.map +1 -1
- package/dist/lib/handlers/types.mjs +0 -6
- package/dist/lib/handlers/types.mjs.map +1 -1
- package/dist/lib/index.mjs +0 -6
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/media-buy/available-actions.mjs +0 -6
- package/dist/lib/media-buy/available-actions.mjs.map +1 -1
- package/dist/lib/media-buy/index.mjs +0 -6
- package/dist/lib/media-buy/index.mjs.map +1 -1
- package/dist/lib/media-buy/preflight.mjs +0 -6
- package/dist/lib/media-buy/preflight.mjs.map +1 -1
- package/dist/lib/media-buy/property-policy.mjs +0 -6
- package/dist/lib/media-buy/property-policy.mjs.map +1 -1
- package/dist/lib/media-buy/types.mjs +0 -6
- package/dist/lib/media-buy/types.mjs.map +1 -1
- package/dist/lib/media-buy/update-fields.generated.mjs +0 -6
- package/dist/lib/media-buy/update-fields.generated.mjs.map +1 -1
- package/dist/lib/mock-server/creative-ad-server/seed-data.mjs +0 -6
- package/dist/lib/mock-server/creative-ad-server/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/creative-ad-server/server.mjs +0 -6
- package/dist/lib/mock-server/creative-ad-server/server.mjs.map +1 -1
- package/dist/lib/mock-server/creative-template/seed-data.mjs +0 -6
- package/dist/lib/mock-server/creative-template/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/creative-template/server.mjs +0 -6
- package/dist/lib/mock-server/creative-template/server.mjs.map +1 -1
- package/dist/lib/mock-server/index.mjs +0 -6
- package/dist/lib/mock-server/index.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/recipe.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/recipe.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/server.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/server.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/server.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/server.mjs.map +1 -1
- package/dist/lib/mock-server/sales-social/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-social/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-social/server.mjs +0 -6
- package/dist/lib/mock-server/sales-social/server.mjs.map +1 -1
- package/dist/lib/mock-server/scenario.mjs +0 -6
- package/dist/lib/mock-server/scenario.mjs.map +1 -1
- package/dist/lib/mock-server/signal-marketplace/seed-data.mjs +0 -6
- package/dist/lib/mock-server/signal-marketplace/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/signal-marketplace/server.mjs +0 -6
- package/dist/lib/mock-server/signal-marketplace/server.mjs.map +1 -1
- package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sponsored-intelligence/server.mjs +0 -6
- package/dist/lib/mock-server/sponsored-intelligence/server.mjs.map +1 -1
- package/dist/lib/net/address-guards.mjs +0 -6
- package/dist/lib/net/address-guards.mjs.map +1 -1
- package/dist/lib/net/index.mjs +0 -6
- package/dist/lib/net/index.mjs.map +1 -1
- package/dist/lib/net/ssrf-fetch.mjs +0 -6
- package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
- package/dist/lib/observability/index.mjs +0 -6
- package/dist/lib/observability/index.mjs.map +1 -1
- package/dist/lib/observability/tracing.mjs +6 -7
- package/dist/lib/observability/tracing.mjs.map +1 -1
- package/dist/lib/protocols/a2a.mjs +0 -6
- package/dist/lib/protocols/a2a.mjs.map +1 -1
- package/dist/lib/protocols/abort.mjs +0 -6
- package/dist/lib/protocols/abort.mjs.map +1 -1
- package/dist/lib/protocols/index.mjs +0 -6
- package/dist/lib/protocols/index.mjs.map +1 -1
- package/dist/lib/protocols/mcp-modern.mjs +0 -6
- package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
- package/dist/lib/protocols/mcp-tasks.mjs +0 -6
- package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
- package/dist/lib/protocols/mcp.mjs +0 -6
- package/dist/lib/protocols/mcp.mjs.map +1 -1
- package/dist/lib/protocols/rawResponseCapture.mjs +0 -6
- package/dist/lib/protocols/rawResponseCapture.mjs.map +1 -1
- package/dist/lib/protocols/responseSizeLimit.mjs +0 -6
- package/dist/lib/protocols/responseSizeLimit.mjs.map +1 -1
- package/dist/lib/protocols/transportDiagnostics.mjs +0 -6
- package/dist/lib/protocols/transportDiagnostics.mjs.map +1 -1
- package/dist/lib/registry/cursor-store.mjs +0 -6
- package/dist/lib/registry/cursor-store.mjs.map +1 -1
- package/dist/lib/registry/feed-stream.mjs +0 -6
- package/dist/lib/registry/feed-stream.mjs.map +1 -1
- package/dist/lib/registry/index.mjs +0 -6
- package/dist/lib/registry/index.mjs.map +1 -1
- package/dist/lib/registry/property-registry.mjs +0 -6
- package/dist/lib/registry/property-registry.mjs.map +1 -1
- package/dist/lib/registry/sync.mjs +0 -6
- package/dist/lib/registry/sync.mjs.map +1 -1
- package/dist/lib/registry/types.generated.mjs +0 -6
- package/dist/lib/registry/types.mjs +0 -6
- package/dist/lib/schemas/index.mjs +0 -6
- package/dist/lib/schemas/index.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/a2a-adapter.mjs +0 -6
- package/dist/lib/server/a2a-adapter.mjs.map +1 -1
- package/dist/lib/server/account-mode.mjs +0 -6
- package/dist/lib/server/account-mode.mjs.map +1 -1
- package/dist/lib/server/adcp-server.mjs +0 -6
- package/dist/lib/server/adcp-server.mjs.map +1 -1
- package/dist/lib/server/auth-introspection.mjs +0 -6
- package/dist/lib/server/auth-introspection.mjs.map +1 -1
- package/dist/lib/server/auth-signature.mjs +0 -6
- package/dist/lib/server/auth-signature.mjs.map +1 -1
- package/dist/lib/server/auth.mjs +0 -6
- package/dist/lib/server/auth.mjs.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +0 -6
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/credential-policy.mjs +0 -6
- package/dist/lib/server/credential-policy.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/memory.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/memory.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/pg.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/pg.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/redis.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/redis.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/index.mjs +0 -6
- package/dist/lib/server/ctx-metadata/index.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/store.mjs +0 -6
- package/dist/lib/server/ctx-metadata/store.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/wire-shape.mjs +0 -6
- package/dist/lib/server/ctx-metadata/wire-shape.mjs.map +1 -1
- package/dist/lib/server/decisioning/account.mjs +0 -6
- package/dist/lib/server/decisioning/account.mjs.map +1 -1
- package/dist/lib/server/decisioning/admin-router.mjs +0 -6
- package/dist/lib/server/decisioning/admin-router.mjs.map +1 -1
- package/dist/lib/server/decisioning/assembly-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/assembly-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/async-outcome.mjs +0 -6
- package/dist/lib/server/decisioning/async-outcome.mjs.map +1 -1
- package/dist/lib/server/decisioning/buyer-agent.mjs +0 -6
- package/dist/lib/server/decisioning/buyer-agent.mjs.map +1 -1
- package/dist/lib/server/decisioning/capabilities.mjs +0 -6
- package/dist/lib/server/decisioning/capabilities.mjs.map +1 -1
- package/dist/lib/server/decisioning/compose.mjs +0 -6
- package/dist/lib/server/decisioning/compose.mjs.map +1 -1
- package/dist/lib/server/decisioning/context.mjs +0 -6
- package/dist/lib/server/decisioning/errors-typed.mjs +0 -6
- package/dist/lib/server/decisioning/errors-typed.mjs.map +1 -1
- package/dist/lib/server/decisioning/helpers.mjs +0 -6
- package/dist/lib/server/decisioning/helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.mjs +0 -6
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/list-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/list-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/manifest-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/pagination.mjs +0 -6
- package/dist/lib/server/decisioning/platform-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/platform-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/platform.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/dispatch.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/dispatch.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/index.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/lifecycle.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/lifecycle.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/mock-manager.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/mock-manager.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/store.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/store.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
- package/dist/lib/server/decisioning/resolve-presets.mjs +0 -6
- package/dist/lib/server/decisioning/resolve-presets.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/observed-modes.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/observed-modes.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/audiences.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/brand-rights.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/campaign-governance.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/content-standards.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/creative.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/lists.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/sales.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/signals.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.mjs +0 -6
- package/dist/lib/server/decisioning/start-time.mjs +0 -6
- package/dist/lib/server/decisioning/start-time.mjs.map +1 -1
- package/dist/lib/server/decisioning/status-changes.mjs +0 -6
- package/dist/lib/server/decisioning/status-changes.mjs.map +1 -1
- package/dist/lib/server/decisioning/status-mappers.mjs +0 -6
- package/dist/lib/server/decisioning/status-mappers.mjs.map +1 -1
- package/dist/lib/server/decisioning/tenant-registry.mjs +0 -6
- package/dist/lib/server/decisioning/tenant-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/tenant-store.mjs +0 -6
- package/dist/lib/server/decisioning/tenant-store.mjs.map +1 -1
- package/dist/lib/server/decisioning/validate-specialisms.mjs +0 -6
- package/dist/lib/server/decisioning/validate-specialisms.mjs.map +1 -1
- package/dist/lib/server/dynamic-registry.mjs +0 -6
- package/dist/lib/server/dynamic-registry.mjs.map +1 -1
- package/dist/lib/server/envelope-allowlist.mjs +0 -6
- package/dist/lib/server/envelope-allowlist.mjs.map +1 -1
- package/dist/lib/server/error-arm-tools.mjs +5 -6
- package/dist/lib/server/error-arm-tools.mjs.map +1 -1
- package/dist/lib/server/errors.mjs +0 -6
- package/dist/lib/server/errors.mjs.map +1 -1
- package/dist/lib/server/example-tld-guard.mjs +0 -6
- package/dist/lib/server/example-tld-guard.mjs.map +1 -1
- package/dist/lib/server/express-adapter.mjs +0 -6
- package/dist/lib/server/express-adapter.mjs.map +1 -1
- package/dist/lib/server/governance.mjs +0 -6
- package/dist/lib/server/governance.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/lazy.mjs +0 -6
- package/dist/lib/server/idempotency/backends/lazy.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/memory.mjs +0 -6
- package/dist/lib/server/idempotency/backends/memory.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/pg.mjs +0 -6
- package/dist/lib/server/idempotency/backends/pg.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/redis.mjs +0 -6
- package/dist/lib/server/idempotency/backends/redis.mjs.map +1 -1
- package/dist/lib/server/idempotency/index.mjs +0 -6
- package/dist/lib/server/idempotency/index.mjs.map +1 -1
- package/dist/lib/server/idempotency/store.mjs +0 -6
- package/dist/lib/server/idempotency/store.mjs.map +1 -1
- package/dist/lib/server/index.mjs +0 -6
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/server/legacy/v5/index.mjs +0 -6
- package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
- package/dist/lib/server/mcp-modern-server.mjs +0 -6
- package/dist/lib/server/mcp-modern-server.mjs.map +1 -1
- package/dist/lib/server/media-buy-actions.mjs +0 -6
- package/dist/lib/server/media-buy-actions.mjs.map +1 -1
- package/dist/lib/server/media-buy-helpers.mjs +0 -6
- package/dist/lib/server/media-buy-helpers.mjs.map +1 -1
- package/dist/lib/server/media-buy-store.mjs +0 -6
- package/dist/lib/server/media-buy-store.mjs.map +1 -1
- package/dist/lib/server/normalize-errors.mjs +0 -6
- package/dist/lib/server/normalize-errors.mjs.map +1 -1
- package/dist/lib/server/operational-platform.mjs +0 -6
- package/dist/lib/server/operational-platform.mjs.map +1 -1
- package/dist/lib/server/pick-safe-details.mjs +0 -6
- package/dist/lib/server/pick-safe-details.mjs.map +1 -1
- package/dist/lib/server/pin-and-bind-fetch.mjs +0 -6
- package/dist/lib/server/pin-and-bind-fetch.mjs.map +1 -1
- package/dist/lib/server/postgres-state-store.mjs +0 -6
- package/dist/lib/server/postgres-state-store.mjs.map +1 -1
- package/dist/lib/server/postgres-task-store.mjs +0 -6
- package/dist/lib/server/postgres-task-store.mjs.map +1 -1
- package/dist/lib/server/product-defaults.mjs +0 -6
- package/dist/lib/server/product-defaults.mjs.map +1 -1
- package/dist/lib/server/redact.mjs +0 -6
- package/dist/lib/server/redact.mjs.map +1 -1
- package/dist/lib/server/responses.mjs +0 -6
- package/dist/lib/server/responses.mjs.map +1 -1
- package/dist/lib/server/serve.mjs +0 -6
- package/dist/lib/server/serve.mjs.map +1 -1
- package/dist/lib/server/socket-mode/conformance-client.mjs +0 -6
- package/dist/lib/server/socket-mode/conformance-client.mjs.map +1 -1
- package/dist/lib/server/socket-mode/index.mjs +0 -6
- package/dist/lib/server/socket-mode/index.mjs.map +1 -1
- package/dist/lib/server/socket-mode/ws-transport.mjs +0 -6
- package/dist/lib/server/socket-mode/ws-transport.mjs.map +1 -1
- package/dist/lib/server/state-machine.mjs +0 -6
- package/dist/lib/server/state-machine.mjs.map +1 -1
- package/dist/lib/server/state-store.mjs +0 -6
- package/dist/lib/server/state-store.mjs.map +1 -1
- package/dist/lib/server/structured-serialize.mjs +0 -6
- package/dist/lib/server/structured-serialize.mjs.map +1 -1
- package/dist/lib/server/targeting-helpers.mjs +0 -6
- package/dist/lib/server/targeting-helpers.mjs.map +1 -1
- package/dist/lib/server/tasks.mjs +0 -6
- package/dist/lib/server/tasks.mjs.map +1 -1
- package/dist/lib/server/test-controller-bridge.mjs +0 -6
- package/dist/lib/server/test-controller-bridge.mjs.map +1 -1
- package/dist/lib/server/test-controller.mjs +0 -6
- package/dist/lib/server/test-controller.mjs.map +1 -1
- package/dist/lib/server/upstream-helpers.mjs +0 -6
- package/dist/lib/server/upstream-helpers.mjs.map +1 -1
- package/dist/lib/server/webhook-emitter.mjs +0 -6
- package/dist/lib/server/webhook-emitter.mjs.map +1 -1
- package/dist/lib/server/wire-safe.mjs +0 -6
- package/dist/lib/server/wire-safe.mjs.map +1 -1
- package/dist/lib/server/wire-spec-fields.generated.mjs +0 -6
- package/dist/lib/server/wire-spec-fields.generated.mjs.map +1 -1
- package/dist/lib/server/wrap-envelope.mjs +0 -6
- package/dist/lib/server/wrap-envelope.mjs.map +1 -1
- package/dist/lib/signing/agent-context.mjs +0 -6
- package/dist/lib/signing/agent-context.mjs.map +1 -1
- package/dist/lib/signing/agent-fetch.mjs +0 -6
- package/dist/lib/signing/agent-fetch.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/canonicalize.mjs +0 -6
- package/dist/lib/signing/agent-resolver/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs +0 -6
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/consistency.mjs +0 -6
- package/dist/lib/signing/agent-resolver/consistency.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/errors.mjs +0 -6
- package/dist/lib/signing/agent-resolver/errors.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/etld.mjs +0 -6
- package/dist/lib/signing/agent-resolver/etld.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +0 -6
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/index.mjs +0 -6
- package/dist/lib/signing/agent-resolver/index.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/jwks-set.mjs +0 -6
- package/dist/lib/signing/agent-resolver/jwks-set.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/select-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/select-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/strict-json.mjs +0 -6
- package/dist/lib/signing/agent-resolver/strict-json.mjs.map +1 -1
- package/dist/lib/signing/brand-jwks.mjs +0 -6
- package/dist/lib/signing/brand-jwks.mjs.map +1 -1
- package/dist/lib/signing/canonicalize.mjs +0 -6
- package/dist/lib/signing/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/capability-cache.mjs +0 -6
- package/dist/lib/signing/capability-cache.mjs.map +1 -1
- package/dist/lib/signing/capability-priming.mjs +0 -6
- package/dist/lib/signing/capability-priming.mjs.map +1 -1
- package/dist/lib/signing/client.mjs +0 -6
- package/dist/lib/signing/client.mjs.map +1 -1
- package/dist/lib/signing/content-digest.mjs +0 -6
- package/dist/lib/signing/content-digest.mjs.map +1 -1
- package/dist/lib/signing/crypto.mjs +0 -6
- package/dist/lib/signing/crypto.mjs.map +1 -1
- package/dist/lib/signing/ecdsa-encoding.mjs +0 -6
- package/dist/lib/signing/ecdsa-encoding.mjs.map +1 -1
- package/dist/lib/signing/errors.mjs +0 -6
- package/dist/lib/signing/errors.mjs.map +1 -1
- package/dist/lib/signing/fetch-async.mjs +0 -6
- package/dist/lib/signing/fetch-async.mjs.map +1 -1
- package/dist/lib/signing/fetch.mjs +0 -6
- package/dist/lib/signing/fetch.mjs.map +1 -1
- package/dist/lib/signing/index.mjs +0 -6
- package/dist/lib/signing/index.mjs.map +1 -1
- package/dist/lib/signing/jwks-helpers.mjs +0 -6
- package/dist/lib/signing/jwks-helpers.mjs.map +1 -1
- package/dist/lib/signing/jwks-https.mjs +0 -6
- package/dist/lib/signing/jwks-https.mjs.map +1 -1
- package/dist/lib/signing/jwks.mjs +0 -6
- package/dist/lib/signing/jwks.mjs.map +1 -1
- package/dist/lib/signing/middleware.mjs +0 -6
- package/dist/lib/signing/middleware.mjs.map +1 -1
- package/dist/lib/signing/parser.mjs +0 -6
- package/dist/lib/signing/parser.mjs.map +1 -1
- package/dist/lib/signing/postgres-replay-store.mjs +0 -6
- package/dist/lib/signing/postgres-replay-store.mjs.map +1 -1
- package/dist/lib/signing/protocol-response.mjs +0 -6
- package/dist/lib/signing/protocol-response.mjs.map +1 -1
- package/dist/lib/signing/provider.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs.map +1 -1
- package/dist/lib/signing/replay.mjs +0 -6
- package/dist/lib/signing/replay.mjs.map +1 -1
- package/dist/lib/signing/request-context.mjs +0 -6
- package/dist/lib/signing/request-context.mjs.map +1 -1
- package/dist/lib/signing/revocation-https.mjs +0 -6
- package/dist/lib/signing/revocation-https.mjs.map +1 -1
- package/dist/lib/signing/revocation.mjs +0 -6
- package/dist/lib/signing/revocation.mjs.map +1 -1
- package/dist/lib/signing/server.mjs +0 -6
- package/dist/lib/signing/server.mjs.map +1 -1
- package/dist/lib/signing/signer-async.mjs +0 -6
- package/dist/lib/signing/signer-async.mjs.map +1 -1
- package/dist/lib/signing/signer.mjs +0 -6
- package/dist/lib/signing/signer.mjs.map +1 -1
- package/dist/lib/signing/testing.mjs +0 -6
- package/dist/lib/signing/testing.mjs.map +1 -1
- package/dist/lib/signing/types.mjs +0 -6
- package/dist/lib/signing/types.mjs.map +1 -1
- package/dist/lib/signing/verifier.mjs +0 -6
- package/dist/lib/signing/verifier.mjs.map +1 -1
- package/dist/lib/signing/webhook-auth-detection.mjs +0 -6
- package/dist/lib/signing/webhook-auth-detection.mjs.map +1 -1
- package/dist/lib/signing/webhook-verifier.mjs +0 -6
- package/dist/lib/signing/webhook-verifier.mjs.map +1 -1
- package/dist/lib/storage/MemoryStorage.mjs +0 -6
- package/dist/lib/storage/MemoryStorage.mjs.map +1 -1
- package/dist/lib/storage/interfaces.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs.map +1 -1
- package/dist/lib/substitution/encoder/index.mjs +0 -6
- package/dist/lib/substitution/encoder/index.mjs.map +1 -1
- package/dist/lib/substitution/index.mjs +0 -6
- package/dist/lib/substitution/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs +0 -6
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs.map +1 -1
- package/dist/lib/substitution/observer/alignment.mjs +0 -6
- package/dist/lib/substitution/observer/alignment.mjs.map +1 -1
- package/dist/lib/substitution/observer/assertions.mjs +0 -6
- package/dist/lib/substitution/observer/assertions.mjs.map +1 -1
- package/dist/lib/substitution/observer/html-parser.mjs +0 -6
- package/dist/lib/substitution/observer/html-parser.mjs.map +1 -1
- package/dist/lib/substitution/observer/index.mjs +0 -6
- package/dist/lib/substitution/observer/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/ssrf.mjs +0 -6
- package/dist/lib/substitution/observer/ssrf.mjs.map +1 -1
- package/dist/lib/substitution/rfc3986.mjs +0 -6
- package/dist/lib/substitution/rfc3986.mjs.map +1 -1
- package/dist/lib/substitution/translate.mjs +0 -6
- package/dist/lib/substitution/translate.mjs.map +1 -1
- package/dist/lib/substitution/types.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs.map +1 -1
- package/dist/lib/testing/agent-tester.mjs +0 -6
- package/dist/lib/testing/agent-tester.mjs.map +1 -1
- package/dist/lib/testing/client.mjs +0 -6
- package/dist/lib/testing/client.mjs.map +1 -1
- package/dist/lib/testing/compliance/briefs.mjs +0 -6
- package/dist/lib/testing/compliance/briefs.mjs.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +0 -6
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/compliance/index.mjs +0 -6
- package/dist/lib/testing/compliance/index.mjs.map +1 -1
- package/dist/lib/testing/compliance/spec-conformance.mjs +0 -6
- package/dist/lib/testing/compliance/spec-conformance.mjs.map +1 -1
- package/dist/lib/testing/compliance/storyboard-tracks.mjs +0 -6
- package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
- package/dist/lib/testing/compliance/summary.mjs +0 -6
- package/dist/lib/testing/compliance/summary.mjs.map +1 -1
- package/dist/lib/testing/compliance/types.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs.map +1 -1
- package/dist/lib/testing/controller-assertions.mjs +0 -6
- package/dist/lib/testing/controller-assertions.mjs.map +1 -1
- package/dist/lib/testing/formatter.mjs +0 -6
- package/dist/lib/testing/formatter.mjs.map +1 -1
- package/dist/lib/testing/index.mjs +0 -6
- package/dist/lib/testing/index.mjs.map +1 -1
- package/dist/lib/testing/local-agent-runner.mjs +0 -6
- package/dist/lib/testing/local-agent-runner.mjs.map +1 -1
- package/dist/lib/testing/orchestrator.mjs +0 -6
- package/dist/lib/testing/orchestrator.mjs.map +1 -1
- package/dist/lib/testing/personas/index.mjs +0 -6
- package/dist/lib/testing/personas/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/brand-rights.mjs +0 -6
- package/dist/lib/testing/scenarios/brand-rights.mjs.map +1 -1
- package/dist/lib/testing/scenarios/capabilities.mjs +0 -6
- package/dist/lib/testing/scenarios/capabilities.mjs.map +1 -1
- package/dist/lib/testing/scenarios/creative.mjs +0 -6
- package/dist/lib/testing/scenarios/creative.mjs.map +1 -1
- package/dist/lib/testing/scenarios/deterministic.mjs +0 -6
- package/dist/lib/testing/scenarios/deterministic.mjs.map +1 -1
- package/dist/lib/testing/scenarios/discovery.mjs +0 -6
- package/dist/lib/testing/scenarios/discovery.mjs.map +1 -1
- package/dist/lib/testing/scenarios/edge-cases.mjs +0 -6
- package/dist/lib/testing/scenarios/edge-cases.mjs.map +1 -1
- package/dist/lib/testing/scenarios/error-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/error-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/governance.mjs +0 -6
- package/dist/lib/testing/scenarios/governance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/health.mjs +0 -6
- package/dist/lib/testing/scenarios/health.mjs.map +1 -1
- package/dist/lib/testing/scenarios/index.mjs +0 -6
- package/dist/lib/testing/scenarios/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.mjs +0 -6
- package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/schema-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/signals.mjs +0 -6
- package/dist/lib/testing/scenarios/signals.mjs.map +1 -1
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs +0 -6
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs.map +1 -1
- package/dist/lib/testing/scenarios/trusted-match.mjs +0 -6
- package/dist/lib/testing/scenarios/trusted-match.mjs.map +1 -1
- package/dist/lib/testing/seed-merge.mjs +0 -6
- package/dist/lib/testing/seed-merge.mjs.map +1 -1
- package/dist/lib/testing/storyboard/agent-routing.mjs +0 -6
- package/dist/lib/testing/storyboard/agent-routing.mjs.map +1 -1
- package/dist/lib/testing/storyboard/assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +0 -6
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs.map +1 -1
- package/dist/lib/testing/storyboard/compliance.mjs +5 -6
- package/dist/lib/testing/storyboard/compliance.mjs.map +1 -1
- package/dist/lib/testing/storyboard/context.mjs +0 -6
- package/dist/lib/testing/storyboard/context.mjs.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.mjs +0 -6
- package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
- package/dist/lib/testing/storyboard/index.mjs +0 -6
- package/dist/lib/testing/storyboard/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/junit.mjs +0 -6
- package/dist/lib/testing/storyboard/junit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/loader.mjs +0 -6
- package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/path.mjs +0 -6
- package/dist/lib/testing/storyboard/path.mjs.map +1 -1
- package/dist/lib/testing/storyboard/probes.mjs +0 -6
- package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs +0 -6
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rejection-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/rejection-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/index.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/types.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +0 -6
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/sandbox-entities.mjs +0 -6
- package/dist/lib/testing/storyboard/sandbox-entities.mjs.map +1 -1
- package/dist/lib/testing/storyboard/seeding.mjs +0 -6
- package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/index.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/types.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/task-map.mjs +0 -6
- package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
- package/dist/lib/testing/storyboard/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/types.mjs +0 -6
- package/dist/lib/testing/storyboard/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.mjs +0 -6
- package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
- package/dist/lib/testing/stubs/governance-agent-stub.mjs +0 -6
- package/dist/lib/testing/stubs/governance-agent-stub.mjs.map +1 -1
- package/dist/lib/testing/stubs/index.mjs +0 -6
- package/dist/lib/testing/stubs/index.mjs.map +1 -1
- package/dist/lib/testing/test-controller.mjs +0 -6
- package/dist/lib/testing/test-controller.mjs.map +1 -1
- package/dist/lib/testing/test-helpers.mjs +0 -6
- package/dist/lib/testing/test-helpers.mjs.map +1 -1
- package/dist/lib/testing/types.mjs +0 -6
- package/dist/lib/types/adcp.mjs +0 -6
- package/dist/lib/types/adcp.mjs.map +1 -1
- package/dist/lib/types/asset-instances.mjs +0 -6
- package/dist/lib/types/compat.mjs +0 -6
- package/dist/lib/types/compat.mjs.map +1 -1
- package/dist/lib/types/core.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs.map +1 -1
- package/dist/lib/types/error-codes.mjs +0 -6
- package/dist/lib/types/error-codes.mjs.map +1 -1
- package/dist/lib/types/error-details.aliases.mjs +0 -6
- package/dist/lib/types/error-details.aliases.mjs.map +1 -1
- package/dist/lib/types/format-asset-slots.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs.map +1 -1
- package/dist/lib/types/index.mjs +0 -6
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/types/inline-enums.aliases.mjs +0 -6
- package/dist/lib/types/inline-enums.aliases.mjs.map +1 -1
- package/dist/lib/types/inline-enums.generated.mjs +0 -6
- package/dist/lib/types/inline-enums.generated.mjs.map +1 -1
- package/dist/lib/types/manifest.generated.mjs +0 -6
- package/dist/lib/types/manifest.generated.mjs.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +0 -6
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/server-payload-aliases.mjs +0 -6
- package/dist/lib/types/server-payload.mjs +0 -6
- package/dist/lib/types/sync-rows.mjs +0 -6
- package/dist/lib/types/tools.generated.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs.map +1 -1
- package/dist/lib/types/v2-5/tools.generated.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs.map +1 -1
- package/dist/lib/types/v3-1-beta/tools.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs.map +1 -1
- package/dist/lib/upstream-recorder/constants.mjs +0 -6
- package/dist/lib/upstream-recorder/constants.mjs.map +1 -1
- package/dist/lib/upstream-recorder/index.mjs +0 -6
- package/dist/lib/upstream-recorder/index.mjs.map +1 -1
- package/dist/lib/upstream-recorder/recorder.mjs +0 -6
- package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
- package/dist/lib/upstream-recorder/types.mjs +0 -6
- package/dist/lib/upstream-recorder/types.mjs.map +1 -1
- package/dist/lib/utils/a2a-artifacts.mjs +0 -6
- package/dist/lib/utils/a2a-artifacts.mjs.map +1 -1
- package/dist/lib/utils/a2a-discovery.mjs +0 -6
- package/dist/lib/utils/a2a-discovery.mjs.map +1 -1
- package/dist/lib/utils/activation-key-builders.mjs +0 -6
- package/dist/lib/utils/activation-key-builders.mjs.map +1 -1
- package/dist/lib/utils/adcp-version-config.mjs +0 -6
- package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
- package/dist/lib/utils/asset-builders.mjs +0 -6
- package/dist/lib/utils/asset-builders.mjs.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.mjs +0 -6
- package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
- package/dist/lib/utils/buyer-retry-policy.mjs +0 -6
- package/dist/lib/utils/buyer-retry-policy.mjs.map +1 -1
- package/dist/lib/utils/capabilities.mjs +0 -6
- package/dist/lib/utils/capabilities.mjs.map +1 -1
- package/dist/lib/utils/capability-rollups.mjs +0 -6
- package/dist/lib/utils/capability-rollups.mjs.map +1 -1
- package/dist/lib/utils/creative-adapter.mjs +0 -6
- package/dist/lib/utils/creative-adapter.mjs.map +1 -1
- package/dist/lib/utils/creative-delivery.mjs +0 -6
- package/dist/lib/utils/creative-delivery.mjs.map +1 -1
- package/dist/lib/utils/deprecation.mjs +0 -6
- package/dist/lib/utils/deprecation.mjs.map +1 -1
- package/dist/lib/utils/envelope-status-compat.mjs +0 -6
- package/dist/lib/utils/envelope-status-compat.mjs.map +1 -1
- package/dist/lib/utils/error-extraction.mjs +0 -6
- package/dist/lib/utils/error-extraction.mjs.map +1 -1
- package/dist/lib/utils/extract-result.mjs +0 -6
- package/dist/lib/utils/extract-result.mjs.map +1 -1
- package/dist/lib/utils/format-asset-slot-builders.mjs +0 -6
- package/dist/lib/utils/format-asset-slot-builders.mjs.map +1 -1
- package/dist/lib/utils/format-assets.mjs +0 -6
- package/dist/lib/utils/format-assets.mjs.map +1 -1
- package/dist/lib/utils/format-render-builders.mjs +0 -6
- package/dist/lib/utils/format-render-builders.mjs.map +1 -1
- package/dist/lib/utils/format-renders.mjs +0 -6
- package/dist/lib/utils/format-renders.mjs.map +1 -1
- package/dist/lib/utils/get-products-cache-scope.mjs +0 -6
- package/dist/lib/utils/get-products-cache-scope.mjs.map +1 -1
- package/dist/lib/utils/glob.mjs +0 -6
- package/dist/lib/utils/glob.mjs.map +1 -1
- package/dist/lib/utils/global-async-local-storage.mjs +0 -6
- package/dist/lib/utils/global-async-local-storage.mjs.map +1 -1
- package/dist/lib/utils/idempotency.mjs +0 -6
- package/dist/lib/utils/idempotency.mjs.map +1 -1
- package/dist/lib/utils/index.mjs +0 -6
- package/dist/lib/utils/index.mjs.map +1 -1
- package/dist/lib/utils/jcs.mjs +0 -6
- package/dist/lib/utils/jcs.mjs.map +1 -1
- package/dist/lib/utils/json-depth.mjs +0 -6
- package/dist/lib/utils/json-depth.mjs.map +1 -1
- package/dist/lib/utils/logger.mjs +0 -6
- package/dist/lib/utils/logger.mjs.map +1 -1
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs +0 -6
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs.map +1 -1
- package/dist/lib/utils/media-buy-status.mjs +0 -6
- package/dist/lib/utils/media-buy-status.mjs.map +1 -1
- package/dist/lib/utils/pagination.mjs +0 -6
- package/dist/lib/utils/pagination.mjs.map +1 -1
- package/dist/lib/utils/preview-creative-builders.mjs +0 -6
- package/dist/lib/utils/preview-creative-builders.mjs.map +1 -1
- package/dist/lib/utils/preview-normalizer.mjs +0 -6
- package/dist/lib/utils/preview-normalizer.mjs.map +1 -1
- package/dist/lib/utils/preview-utils.mjs +0 -6
- package/dist/lib/utils/preview-utils.mjs.map +1 -1
- package/dist/lib/utils/pricing-adapter.mjs +0 -6
- package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
- package/dist/lib/utils/probe-policy.mjs +0 -6
- package/dist/lib/utils/probe-policy.mjs.map +1 -1
- package/dist/lib/utils/protocol-detection.mjs +0 -6
- package/dist/lib/utils/protocol-detection.mjs.map +1 -1
- package/dist/lib/utils/redact-secrets.mjs +0 -6
- package/dist/lib/utils/redact-secrets.mjs.map +1 -1
- package/dist/lib/utils/redis-default-prefix-warn.mjs +0 -6
- package/dist/lib/utils/redis-default-prefix-warn.mjs.map +1 -1
- package/dist/lib/utils/render-builders.mjs +0 -6
- package/dist/lib/utils/render-builders.mjs.map +1 -1
- package/dist/lib/utils/request-normalizer.mjs +0 -6
- package/dist/lib/utils/request-normalizer.mjs.map +1 -1
- package/dist/lib/utils/response-schemas.mjs +0 -6
- package/dist/lib/utils/response-schemas.mjs.map +1 -1
- package/dist/lib/utils/response-unwrapper.mjs +0 -6
- package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
- package/dist/lib/utils/retry.mjs +0 -6
- package/dist/lib/utils/retry.mjs.map +1 -1
- package/dist/lib/utils/signal-discovery-helpers.mjs +0 -6
- package/dist/lib/utils/signal-discovery-helpers.mjs.map +1 -1
- package/dist/lib/utils/signal-id-builders.mjs +0 -6
- package/dist/lib/utils/signal-id-builders.mjs.map +1 -1
- package/dist/lib/utils/sync-creatives-adapter.mjs +0 -6
- package/dist/lib/utils/sync-creatives-adapter.mjs.map +1 -1
- package/dist/lib/utils/task-state.mjs +0 -6
- package/dist/lib/utils/task-state.mjs.map +1 -1
- package/dist/lib/utils/tool-request-schemas.mjs +0 -6
- package/dist/lib/utils/tool-request-schemas.mjs.map +1 -1
- package/dist/lib/utils/typeGuards.mjs +0 -6
- package/dist/lib/utils/typeGuards.mjs.map +1 -1
- package/dist/lib/utils/union-errors.mjs +0 -6
- package/dist/lib/utils/union-errors.mjs.map +1 -1
- package/dist/lib/utils/validate-user-agent.mjs +0 -6
- package/dist/lib/utils/validate-user-agent.mjs.map +1 -1
- package/dist/lib/v2/format-schema/fetch.mjs +0 -6
- package/dist/lib/v2/format-schema/fetch.mjs.map +1 -1
- package/dist/lib/v2/format-schema/index.mjs +0 -6
- package/dist/lib/v2/format-schema/index.mjs.map +1 -1
- package/dist/lib/v2/format-schema/regex-safety.mjs +0 -6
- package/dist/lib/v2/format-schema/regex-safety.mjs.map +1 -1
- package/dist/lib/v2/format-schema/resolver.mjs +7 -8
- package/dist/lib/v2/format-schema/resolver.mjs.map +1 -1
- package/dist/lib/v2/format-schema/sandbox-refs.mjs +0 -6
- package/dist/lib/v2/format-schema/sandbox-refs.mjs.map +1 -1
- package/dist/lib/v2/projection/augment-response.mjs +0 -6
- package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
- package/dist/lib/v2/projection/builders.mjs +0 -6
- package/dist/lib/v2/projection/builders.mjs.map +1 -1
- package/dist/lib/v2/projection/cache-versions.mjs +0 -6
- package/dist/lib/v2/projection/cache-versions.mjs.map +1 -1
- package/dist/lib/v2/projection/canonical-properties.mjs +5 -6
- package/dist/lib/v2/projection/canonical-properties.mjs.map +1 -1
- package/dist/lib/v2/projection/catalog.mjs +5 -6
- package/dist/lib/v2/projection/catalog.mjs.map +1 -1
- package/dist/lib/v2/projection/constants.mjs +0 -6
- package/dist/lib/v2/projection/constants.mjs.map +1 -1
- package/dist/lib/v2/projection/index.mjs +0 -6
- package/dist/lib/v2/projection/index.mjs.map +1 -1
- package/dist/lib/v2/projection/registry.mjs +5 -6
- package/dist/lib/v2/projection/registry.mjs.map +1 -1
- package/dist/lib/v2/projection/types.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
- package/dist/lib/v2/projection/v2-to-v1.mjs +0 -6
- package/dist/lib/v2/projection/v2-to-v1.mjs.map +1 -1
- package/dist/lib/v2/projection/write-side.mjs +0 -6
- package/dist/lib/v2/projection/write-side.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/formats.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/formats.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/index.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/index.mjs.map +1 -1
- package/dist/lib/validation/client-hooks.mjs +0 -6
- package/dist/lib/validation/client-hooks.mjs.map +1 -1
- package/dist/lib/validation/hints.mjs +0 -6
- package/dist/lib/validation/hints.mjs.map +1 -1
- package/dist/lib/validation/index.mjs +0 -6
- package/dist/lib/validation/index.mjs.map +1 -1
- package/dist/lib/validation/schema-errors.mjs +0 -6
- package/dist/lib/validation/schema-errors.mjs.map +1 -1
- package/dist/lib/validation/schema-loader.mjs +5 -6
- package/dist/lib/validation/schema-loader.mjs.map +1 -1
- package/dist/lib/validation/schema-validator.mjs +0 -6
- package/dist/lib/validation/schema-validator.mjs.map +1 -1
- package/dist/lib/validation/sync-creatives.mjs +0 -6
- package/dist/lib/validation/sync-creatives.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -9
- package/dist/lib/version.mjs.map +1 -1
- package/dist/lib/webhooks/index.mjs +0 -6
- package/dist/lib/webhooks/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/index.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/sync.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/sync.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/types.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/server/state-store.ts"],"sourcesContent":["/**\n * Pluggable state store for AdCP server domain objects.\n *\n * Sellers use this to persist media buys, accounts, creatives, and other\n * domain state across stateless HTTP requests. The store is a generic\n * document store keyed by collection + id.\n *\n * `createAdcpServer` passes the store to handlers via `ctx.store`.\n * The in-memory implementation works for development; use PostgresStateStore\n * for production.\n *\n * @example\n * ```typescript\n * import { createAdcpServer, InMemoryStateStore } from '@adcp/sdk/server/legacy/v5';\n *\n * const store = new InMemoryStateStore();\n *\n * const server = createAdcpServer({\n * name: 'My Publisher', version: '1.0.0',\n * stateStore: store,\n * mediaBuy: {\n * createMediaBuy: async (params, ctx) => {\n * const buy = { media_buy_id: `mb_${Date.now()}`, status: 'active', packages: [] };\n * await ctx.store.put('media_buys', buy.media_buy_id, buy);\n * return buy;\n * },\n * getMediaBuys: async (params, ctx) => {\n * const buys = await ctx.store.list('media_buys');\n * return { media_buys: buys.items };\n * },\n * },\n * });\n * ```\n */\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nimport { ADCPError } from '../errors';\n\nexport type StateErrorCode = 'INVALID_COLLECTION' | 'INVALID_ID' | 'PAYLOAD_TOO_LARGE' | 'NOT_FOUND' | 'BACKEND_ERROR';\n\n/**\n * Typed error thrown by state-store implementations for validation, size-limit,\n * and backend failures. Extends {@link ADCPError} so callers can use the\n * standard `isADCPError` / `extractErrorInfo` helpers.\n */\nexport class StateError extends ADCPError {\n readonly code: StateErrorCode;\n\n constructor(code: StateErrorCode, message: string, details?: unknown) {\n super(message, details);\n this.code = code;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/** Max bytes (UTF-8) allowed per document. Overridable per-store via options. */\nexport const DEFAULT_MAX_DOCUMENT_BYTES = 5 * 1024 * 1024;\n\n/** 1–256 ASCII letters, digits, or any of `_ - . :`. Prose description is in error messages. */\nconst KEY_PATTERN = /^[A-Za-z0-9_.\\-:]{1,256}$/;\nconst KEY_DESCRIPTION = 'letters, digits, or `_ . - :` (1–256 chars)';\n\n/**\n * Stricter pattern for sessioned-store sessionKeys and ids — excludes `:` so\n * that `sessionKey + \"::\" + id` is unambiguous. Without this, `\"alice:\" + \"::\" + \"x\"`\n * would collide with `\"alice\" + \"::\" + \":x\"` and let tenants read each other's rows.\n */\nconst SESSION_KEY_PATTERN = /^[A-Za-z0-9_.\\-]{1,256}$/;\nconst SESSION_KEY_DESCRIPTION = 'letters, digits, or `_ . -` (1–256 chars; `:` is reserved for scope paths)';\n\n/** Clamp attacker-controlled input before interpolating into error messages or logs. */\nfunction safeForMessage(value: unknown): string {\n const raw = typeof value === 'string' ? value : String(value);\n return raw.slice(0, 64).replace(/[^\\x20-\\x7E]/g, '?');\n}\n\nfunction validateKey(kind: 'collection' | 'id', value: string): void {\n if (typeof value !== 'string' || !KEY_PATTERN.test(value)) {\n const code: StateErrorCode = kind === 'collection' ? 'INVALID_COLLECTION' : 'INVALID_ID';\n throw new StateError(code, `${kind} \"${safeForMessage(value)}\" is invalid. Use ${KEY_DESCRIPTION}.`);\n }\n}\n\nexport function validateCollection(collection: string): void {\n validateKey('collection', collection);\n}\n\nexport function validateId(id: string): void {\n validateKey('id', id);\n}\n\nexport function validatePayloadSize(data: unknown, maxBytes: number): void {\n measureAndCheckSize(data, maxBytes);\n}\n\n/**\n * Measure the serialized size of `data` and throw if it exceeds `maxBytes`.\n * Returns the serialized form so callers can pass it to `db.query` without re-stringifying.\n */\nfunction measureAndCheckSize(data: unknown, maxBytes: number): string {\n const serialized = JSON.stringify(data) ?? '';\n const bytes = Buffer.byteLength(serialized, 'utf8');\n if (bytes > maxBytes) {\n throw new StateError(\n 'PAYLOAD_TOO_LARGE',\n `Document is ${bytes} bytes; exceeds limit of ${maxBytes} bytes. Split the document or raise maxDocumentBytes.`\n );\n }\n return serialized;\n}\n\n/**\n * Validate collection + id + payload size. Returns the serialized payload so\n * callers (e.g., PostgresStateStore) can reuse it without re-stringifying.\n */\nexport function validateWrite(collection: string, id: string, data: unknown, maxBytes: number): string {\n validateKey('collection', collection);\n validateKey('id', id);\n return measureAndCheckSize(data, maxBytes);\n}\n\n// ---------------------------------------------------------------------------\n// Interface\n// ---------------------------------------------------------------------------\n\nexport interface ListOptions {\n /** Filter by field values (exact match). */\n filter?: Record<string, unknown>;\n /** Maximum items to return. */\n limit?: number;\n /** Cursor from a previous list call. */\n cursor?: string;\n}\n\nexport interface ListResult<T = Record<string, unknown>> {\n items: T[];\n nextCursor?: string;\n}\n\n/**\n * Document and its row version, returned by {@link AdcpStateStore.getWithVersion}.\n *\n * `version` is a monotonically increasing integer that starts at `1` on first\n * write and increments by `1` on every `put`/`patch`/`putIfMatch`. Use it with\n * `putIfMatch` to implement optimistic concurrency.\n */\nexport interface VersionedDocument<T = Record<string, unknown>> {\n data: T;\n version: number;\n}\n\n/**\n * Result of an optimistic-concurrency write. Split on `ok` — success gives you\n * the new row version; failure gives you the current version the store has on\n * disk (or `null` if the row doesn't exist) so you can re-read, re-compute, and retry.\n *\n * **Conflict semantics**: `currentVersion` is a best-effort snapshot of the row\n * at conflict-report time, which may be later than the exact moment the CAS\n * failed — another writer can slip in between the failed write and the follow-up\n * read. This is fine for the retry loop in {@link patchWithRetry} (which just\n * re-reads anyway). Direct callers using `currentVersion` for anything beyond\n * \"retry if it changed\" should account for that race.\n */\nexport type PutIfMatchResult = { ok: true; version: number } | { ok: false; currentVersion: number | null };\n\n/**\n * Generic document store for AdCP domain objects.\n *\n * Collections are logical groupings (e.g., 'media_buys', 'accounts', 'creatives').\n * Each document is identified by collection + id.\n */\nexport interface AdcpStateStore {\n /** Get a document by collection and id. Returns null if not found. */\n get<T extends Record<string, unknown> = Record<string, unknown>>(collection: string, id: string): Promise<T | null>;\n\n /** Create or replace a document (upsert semantics). */\n put(collection: string, id: string, data: Record<string, unknown>): Promise<void>;\n\n /**\n * Merge fields into an existing document. Creates the document if it doesn't exist.\n * Only top-level fields are merged — nested objects are replaced, not deep-merged.\n */\n patch(collection: string, id: string, partial: Record<string, unknown>): Promise<void>;\n\n /** Delete a document. Returns true if it existed. */\n delete(collection: string, id: string): Promise<boolean>;\n\n /** List documents in a collection with optional filtering and pagination. */\n list<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n options?: ListOptions\n ): Promise<ListResult<T>>;\n\n /**\n * Convenience method for built-in stores: returns a session-scoped view.\n * Optional on the interface so custom `AdcpStateStore` implementations\n * aren't forced to implement it — callers who need the wrapper on any\n * store should use {@link scopedStore} instead, which handles the fallback.\n */\n scoped?(sessionKey: string): AdcpStateStore;\n\n /**\n * Read a document with its current row version. Returns `null` if the row\n * doesn't exist. Optional on the interface — custom stores that don't\n * track versions don't have to implement it. Use {@link patchWithRetry} to\n * guard against read-modify-write races without calling this directly.\n */\n getWithVersion?<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<VersionedDocument<T> | null>;\n\n /**\n * Atomic compare-and-swap write. Succeeds only if the row's current version\n * equals `expectedVersion` (or if the row doesn't exist and `expectedVersion`\n * is `null`). On conflict, returns the version the store actually has so the\n * caller can re-read and retry.\n *\n * Optional on the interface — custom stores that can't implement CAS don't\n * have to. Use {@link patchWithRetry} for the common \"update a field with\n * retry on conflict\" case.\n */\n putIfMatch?(\n collection: string,\n id: string,\n data: Record<string, unknown>,\n expectedVersion: number | null\n ): Promise<PutIfMatchResult>;\n}\n\n/**\n * Return a session-scoped view of any `AdcpStateStore`.\n *\n * Prefers `store.scoped(sessionKey)` when the store defines it; otherwise\n * wraps with {@link createSessionedStore}. Use this in SDK code and skills\n * so custom store implementations work without requiring them to implement\n * `scoped` themselves.\n *\n * ```ts\n * import { scopedStore } from '@adcp/sdk/server';\n *\n * const sessionStore = scopedStore(ctx.store, ctx.sessionKey!);\n * await sessionStore.put('media_buys', buyId, buy);\n * const { items } = await sessionStore.list('media_buys');\n * ```\n */\nexport function scopedStore(store: AdcpStateStore, sessionKey: string): AdcpStateStore {\n return store.scoped ? store.scoped(sessionKey) : createSessionedStore(store, sessionKey);\n}\n\n// ---------------------------------------------------------------------------\n// InMemoryStateStore\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_PAGE_SIZE = 50;\nconst MAX_PAGE_SIZE = 500;\n\nexport interface InMemoryStateStoreOptions {\n /** Max bytes per document. Defaults to {@link DEFAULT_MAX_DOCUMENT_BYTES}. */\n maxDocumentBytes?: number;\n}\n\ninterface VersionedRow {\n data: Record<string, unknown>;\n version: number;\n}\n\n/**\n * In-memory state store for development and testing.\n *\n * State is lost when the process restarts. Use PostgresStateStore for production.\n */\nexport class InMemoryStateStore implements AdcpStateStore {\n private collections = new Map<string, Map<string, VersionedRow>>();\n private readonly maxDocumentBytes: number;\n\n constructor(options?: InMemoryStateStoreOptions) {\n this.maxDocumentBytes = options?.maxDocumentBytes ?? DEFAULT_MAX_DOCUMENT_BYTES;\n }\n\n private getCollection(collection: string): Map<string, VersionedRow> {\n let col = this.collections.get(collection);\n if (!col) {\n col = new Map();\n this.collections.set(collection, col);\n }\n return col;\n }\n\n async get<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<T | null> {\n validateCollection(collection);\n validateId(id);\n const row = this.getCollection(collection).get(id);\n return row ? ({ ...row.data } as T) : null;\n }\n\n async getWithVersion<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<VersionedDocument<T> | null> {\n validateCollection(collection);\n validateId(id);\n const row = this.getCollection(collection).get(id);\n return row ? { data: { ...row.data } as T, version: row.version } : null;\n }\n\n async put(collection: string, id: string, data: Record<string, unknown>): Promise<void> {\n validateWrite(collection, id, data, this.maxDocumentBytes);\n const col = this.getCollection(collection);\n const existing = col.get(id);\n col.set(id, { data: { ...data }, version: (existing?.version ?? 0) + 1 });\n }\n\n async putIfMatch(\n collection: string,\n id: string,\n data: Record<string, unknown>,\n expectedVersion: number | null\n ): Promise<PutIfMatchResult> {\n validateWrite(collection, id, data, this.maxDocumentBytes);\n const col = this.getCollection(collection);\n const existing = col.get(id);\n const currentVersion = existing?.version ?? null;\n if (currentVersion !== expectedVersion) {\n return { ok: false, currentVersion };\n }\n const nextVersion = (existing?.version ?? 0) + 1;\n col.set(id, { data: { ...data }, version: nextVersion });\n return { ok: true, version: nextVersion };\n }\n\n async patch(collection: string, id: string, partial: Record<string, unknown>): Promise<void> {\n validateWrite(collection, id, partial, this.maxDocumentBytes);\n const col = this.getCollection(collection);\n const existing = col.get(id);\n col.set(id, {\n data: { ...(existing?.data ?? {}), ...partial },\n version: (existing?.version ?? 0) + 1,\n });\n }\n\n async delete(collection: string, id: string): Promise<boolean> {\n validateCollection(collection);\n validateId(id);\n return this.getCollection(collection).delete(id);\n }\n\n async list<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n options?: ListOptions\n ): Promise<ListResult<T>> {\n validateCollection(collection);\n const col = this.getCollection(collection);\n\n let entries = [...col.entries()].map(([id, row]) => ({ id, data: row.data as T }));\n\n if (options?.filter) {\n for (const [key, value] of Object.entries(options.filter)) {\n entries = entries.filter(e => e.data[key] === value);\n }\n }\n\n if (options?.cursor) {\n const idx = entries.findIndex(e => e.id === options.cursor);\n if (idx >= 0) {\n entries = entries.slice(idx + 1);\n }\n }\n\n const limit = Math.min(options?.limit ?? DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);\n const hasMore = entries.length > limit;\n entries = entries.slice(0, limit);\n\n const nextCursor = hasMore && entries.length > 0 ? entries[entries.length - 1]!.id : undefined;\n\n return { items: entries.map(e => ({ ...e.data })), nextCursor };\n }\n\n /** Clear all data. Useful in tests. */\n clear(): void {\n this.collections.clear();\n }\n\n /** Get the number of documents in a collection. */\n size(collection: string): number {\n return this.getCollection(collection).size;\n }\n\n scoped(sessionKey: string): AdcpStateStore {\n return createSessionedStore(this, sessionKey);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Sessioned store wrapper\n// ---------------------------------------------------------------------------\n\n/**\n * Marker field injected by {@link createSessionedStore} into every document\n * it writes. Sellers reading the underlying store directly will see it.\n */\nexport const SESSION_KEY_FIELD = '_session_key';\n\n/** Reserved scope-path separator. `:` is forbidden in sessionKeys and ids so `::` is unambiguous. */\nconst SESSION_ID_SEPARATOR = '::';\n\nfunction validateSessionPart(kind: 'sessionKey' | 'id', value: string): void {\n if (typeof value !== 'string' || !SESSION_KEY_PATTERN.test(value)) {\n throw new StateError(\n 'INVALID_ID',\n `${kind} \"${safeForMessage(value)}\" is invalid. Use ${SESSION_KEY_DESCRIPTION}.`\n );\n }\n}\n\nfunction stripSessionKey<T extends Record<string, unknown>>(doc: T | null): T | null {\n if (doc == null) return null;\n if (!(SESSION_KEY_FIELD in doc)) return doc;\n const { [SESSION_KEY_FIELD]: _ignored, ...rest } = doc as Record<string, unknown>;\n return rest as T;\n}\n\nfunction rejectReservedField(data: Record<string, unknown>): void {\n if (SESSION_KEY_FIELD in data) {\n throw new StateError(\n 'INVALID_ID',\n `Payload field \"${SESSION_KEY_FIELD}\" is reserved by the sessioned store. Rename it in your document.`\n );\n }\n}\n\n/**\n * Wrap an AdcpStateStore so every operation is isolated to `sessionKey`.\n *\n * - **ids** are prefixed with `${sessionKey}::` before hitting the underlying store.\n * - **writes** inject `_session_key: sessionKey` into the document so `list()` can filter on it.\n * - **reads/lists** strip `_session_key` before returning documents.\n * - **list filters** always AND-in `_session_key = sessionKey`.\n *\n * `sessionKey` and caller `id`s must match {@link SESSION_KEY_PATTERN} — no `:`\n * characters — so `${sessionKey}::${id}` is unambiguous. Payloads may not include\n * the reserved `_session_key` field.\n *\n * Use this when every handler's state is scoped to a tenant/brand/session,\n * so you don't have to thread `sessionKey` through every `put`/`list` call.\n */\nexport function createSessionedStore(inner: AdcpStateStore, sessionKey: string): AdcpStateStore {\n validateSessionPart('sessionKey', sessionKey);\n\n const prefix = (id: string) => {\n validateSessionPart('id', id);\n return `${sessionKey}${SESSION_ID_SEPARATOR}${id}`;\n };\n\n return {\n async get<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<T | null> {\n const doc = await inner.get<T>(collection, prefix(id));\n return stripSessionKey(doc);\n },\n\n async put(collection, id, data) {\n rejectReservedField(data);\n await inner.put(collection, prefix(id), { ...data, [SESSION_KEY_FIELD]: sessionKey });\n },\n\n async patch(collection, id, partial) {\n rejectReservedField(partial);\n await inner.patch(collection, prefix(id), { ...partial, [SESSION_KEY_FIELD]: sessionKey });\n },\n\n async delete(collection, id) {\n return inner.delete(collection, prefix(id));\n },\n\n async list<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n options?: ListOptions\n ): Promise<ListResult<T>> {\n const mergedFilter = {\n ...(options?.filter ?? {}),\n [SESSION_KEY_FIELD]: sessionKey,\n };\n const { items, nextCursor } = await inner.list<T>(collection, {\n ...options,\n filter: mergedFilter,\n });\n const stripped = items.map(item => stripSessionKey(item) as T);\n return nextCursor !== undefined ? { items: stripped, nextCursor } : { items: stripped };\n },\n\n // Proxy optimistic-concurrency methods when the inner store supports them.\n // Capture method references at wrap time (bound to `inner`) so runtime\n // reassignment or `this`-sensitive implementations like PostgresStateStore\n // can't desync.\n ...(() => {\n const innerGetWithVersion = inner.getWithVersion?.bind(inner);\n const innerPutIfMatch = inner.putIfMatch?.bind(inner);\n return {\n ...(innerGetWithVersion && {\n async getWithVersion<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<VersionedDocument<T> | null> {\n const result = await innerGetWithVersion<T>(collection, prefix(id));\n if (result == null) return null;\n const stripped = stripSessionKey(result.data);\n return stripped == null ? null : { data: stripped as T, version: result.version };\n },\n }),\n ...(innerPutIfMatch && {\n async putIfMatch(\n collection: string,\n id: string,\n data: Record<string, unknown>,\n expectedVersion: number | null\n ): Promise<PutIfMatchResult> {\n rejectReservedField(data);\n return innerPutIfMatch(\n collection,\n prefix(id),\n { ...data, [SESSION_KEY_FIELD]: sessionKey },\n expectedVersion\n );\n },\n }),\n };\n })(),\n };\n}\n\n// ---------------------------------------------------------------------------\n// patchWithRetry helper\n// ---------------------------------------------------------------------------\n\nexport interface PatchWithRetryOptions {\n /** Max retry attempts on version conflict. Defaults to 5. */\n maxAttempts?: number;\n\n /**\n * Called to compute a millisecond delay before the next attempt. Receives the\n * attempt number that just failed (1-indexed). Defaults to jittered exponential\n * backoff: `Math.random() * (1 << attempt)` (0–2 ms after 1, 0–4 ms after 2, …).\n * Return `0` (or pass a function that does) to disable backoff.\n */\n backoffMs?: (attempt: number) => number;\n\n /**\n * When the row is deleted between the initial read and the write, `patchWithRetry`\n * normally aborts with `PatchConflictError` to avoid silently resurrecting a\n * deleted document. Set to `true` to treat the post-delete state as a fresh\n * insert (re-running `update(null)` and inserting the result).\n *\n * Default: `false`.\n */\n allowResurrection?: boolean;\n}\n\n// Cap the shift so `1 << attempt` can't overflow to 0 or flip sign at attempt >= 31.\n// 20 is plenty: 2^20 = ~1 second, and maxAttempts would be absurd long before then.\nconst defaultBackoffMs = (attempt: number) => Math.random() * Math.pow(2, Math.min(attempt, 20));\n\n/**\n * Error thrown when `patchWithRetry` exceeds `maxAttempts` consecutive version conflicts,\n * or when the row was deleted between the initial read and the write and\n * `allowResurrection` is not set.\n */\nexport class PatchConflictError extends ADCPError {\n readonly code = 'PATCH_CONFLICT';\n constructor(\n readonly collection: string,\n readonly id: string,\n readonly attempts: number,\n readonly reason: 'max_attempts_exceeded' | 'deleted_during_retry',\n readonly lastObservedVersion: number | null\n ) {\n super(\n reason === 'deleted_during_retry'\n ? `patchWithRetry(${collection}, ${id}): row was deleted between read and write. ` +\n `Pass {allowResurrection: true} if you want to re-insert it.`\n : `patchWithRetry(${collection}, ${id}) exhausted ${attempts} attempts after version conflicts ` +\n `(last observed version: ${lastObservedVersion ?? 'none'}). ` +\n `Either the row has too many concurrent writers (split it), or raise {maxAttempts: N}.`\n );\n }\n}\n\n/**\n * Type guard for the conflict arm of {@link PutIfMatchResult}. Useful for\n * narrowing in hand-rolled retry loops.\n *\n * ```ts\n * const result = await store.putIfMatch('col', 'x', data, version);\n * if (isPutIfMatchConflict(result)) {\n * // result.currentVersion is number | null here\n * }\n * ```\n */\nexport function isPutIfMatchConflict(result: PutIfMatchResult): result is { ok: false; currentVersion: number | null } {\n return result.ok === false;\n}\n\n/**\n * Read-compute-write loop that retries on version conflict, using `getWithVersion`\n * + `putIfMatch` under the hood. The right primitive for counter-like updates\n * where two handlers might read the same pre-state and otherwise lose one write.\n *\n * `update` receives the current document (or `null` if the row doesn't exist)\n * and returns the next document. Returning `null` aborts without writing.\n *\n * ```ts\n * await patchWithRetry(ctx.store, 'media_buys', 'mb_1', (current) => ({\n * ...(current ?? {}),\n * budget_spent: (current?.budget_spent ?? 0) + cost,\n * }));\n * ```\n *\n * Throws {@link PatchConflictError} after `maxAttempts` consecutive conflicts.\n * Throws {@link PatchConflictError} with `reason: 'deleted_during_retry'` if\n * the row is deleted between the initial read and the write (opt into\n * resurrection via `allowResurrection: true`).\n *\n * Requires the store to implement both `getWithVersion` and `putIfMatch`.\n *\n * **Mutation caveat**: always build a fresh object in `update` — never mutate\n * the `current` argument in place. In-memory stores hand out a shallow copy\n * (nested references shared across retries) while Postgres deserializes JSONB\n * fresh each time; the safe pattern (`{ ...current, field: newValue }`) works\n * on both.\n *\n * **Error propagation**: if `update` throws, the exception propagates\n * immediately and no retry happens.\n *\n * **Backoff**: default is jittered exponential (low single-digit ms). Override\n * with `options.backoffMs`. Return `0` to disable.\n *\n * **Size**: each retry re-reads the full document. Avoid on rows close to\n * `maxDocumentBytes` — split into per-entity rows instead.\n */\nexport async function patchWithRetry<T extends Record<string, unknown> = Record<string, unknown>>(\n store: AdcpStateStore,\n collection: string,\n id: string,\n update: (current: T | null) => T | null,\n options: PatchWithRetryOptions = {}\n): Promise<T | null> {\n if (!store.getWithVersion || !store.putIfMatch) {\n throw new StateError(\n 'BACKEND_ERROR',\n 'patchWithRetry requires a store with getWithVersion and putIfMatch. Use InMemoryStateStore or PostgresStateStore, or pass a custom store that implements both.'\n );\n }\n\n const maxAttempts = options.maxAttempts ?? 5;\n const backoffMs = options.backoffMs ?? defaultBackoffMs;\n const allowResurrection = options.allowResurrection ?? false;\n\n let sawExistingRow = false;\n let lastObservedVersion: number | null = null;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const current = await store.getWithVersion<T>(collection, id);\n if (current) {\n sawExistingRow = true;\n lastObservedVersion = current.version;\n } else if (sawExistingRow && !allowResurrection) {\n throw new PatchConflictError(collection, id, attempt, 'deleted_during_retry', lastObservedVersion);\n }\n\n const nextData = update(current ? current.data : null);\n if (nextData === null) return null;\n\n const result = await store.putIfMatch(collection, id, nextData, current ? current.version : null);\n if (result.ok) return nextData;\n\n if (result.currentVersion !== null) lastObservedVersion = result.currentVersion;\n\n if (attempt < maxAttempts) {\n const delay = backoffMs(attempt);\n if (delay > 0) await new Promise(r => setTimeout(r, delay));\n }\n }\n throw new PatchConflictError(collection, id, maxAttempts, 'max_attempts_exceeded', lastObservedVersion);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/server/state-store.ts"],"sourcesContent":["/**\n * Pluggable state store for AdCP server domain objects.\n *\n * Sellers use this to persist media buys, accounts, creatives, and other\n * domain state across stateless HTTP requests. The store is a generic\n * document store keyed by collection + id.\n *\n * `createAdcpServer` passes the store to handlers via `ctx.store`.\n * The in-memory implementation works for development; use PostgresStateStore\n * for production.\n *\n * @example\n * ```typescript\n * import { createAdcpServer, InMemoryStateStore } from '@adcp/sdk/server/legacy/v5';\n *\n * const store = new InMemoryStateStore();\n *\n * const server = createAdcpServer({\n * name: 'My Publisher', version: '1.0.0',\n * stateStore: store,\n * mediaBuy: {\n * createMediaBuy: async (params, ctx) => {\n * const buy = { media_buy_id: `mb_${Date.now()}`, status: 'active', packages: [] };\n * await ctx.store.put('media_buys', buy.media_buy_id, buy);\n * return buy;\n * },\n * getMediaBuys: async (params, ctx) => {\n * const buys = await ctx.store.list('media_buys');\n * return { media_buys: buys.items };\n * },\n * },\n * });\n * ```\n */\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nimport { ADCPError } from '../errors';\n\nexport type StateErrorCode = 'INVALID_COLLECTION' | 'INVALID_ID' | 'PAYLOAD_TOO_LARGE' | 'NOT_FOUND' | 'BACKEND_ERROR';\n\n/**\n * Typed error thrown by state-store implementations for validation, size-limit,\n * and backend failures. Extends {@link ADCPError} so callers can use the\n * standard `isADCPError` / `extractErrorInfo` helpers.\n */\nexport class StateError extends ADCPError {\n readonly code: StateErrorCode;\n\n constructor(code: StateErrorCode, message: string, details?: unknown) {\n super(message, details);\n this.code = code;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/** Max bytes (UTF-8) allowed per document. Overridable per-store via options. */\nexport const DEFAULT_MAX_DOCUMENT_BYTES = 5 * 1024 * 1024;\n\n/** 1–256 ASCII letters, digits, or any of `_ - . :`. Prose description is in error messages. */\nconst KEY_PATTERN = /^[A-Za-z0-9_.\\-:]{1,256}$/;\nconst KEY_DESCRIPTION = 'letters, digits, or `_ . - :` (1–256 chars)';\n\n/**\n * Stricter pattern for sessioned-store sessionKeys and ids — excludes `:` so\n * that `sessionKey + \"::\" + id` is unambiguous. Without this, `\"alice:\" + \"::\" + \"x\"`\n * would collide with `\"alice\" + \"::\" + \":x\"` and let tenants read each other's rows.\n */\nconst SESSION_KEY_PATTERN = /^[A-Za-z0-9_.\\-]{1,256}$/;\nconst SESSION_KEY_DESCRIPTION = 'letters, digits, or `_ . -` (1–256 chars; `:` is reserved for scope paths)';\n\n/** Clamp attacker-controlled input before interpolating into error messages or logs. */\nfunction safeForMessage(value: unknown): string {\n const raw = typeof value === 'string' ? value : String(value);\n return raw.slice(0, 64).replace(/[^\\x20-\\x7E]/g, '?');\n}\n\nfunction validateKey(kind: 'collection' | 'id', value: string): void {\n if (typeof value !== 'string' || !KEY_PATTERN.test(value)) {\n const code: StateErrorCode = kind === 'collection' ? 'INVALID_COLLECTION' : 'INVALID_ID';\n throw new StateError(code, `${kind} \"${safeForMessage(value)}\" is invalid. Use ${KEY_DESCRIPTION}.`);\n }\n}\n\nexport function validateCollection(collection: string): void {\n validateKey('collection', collection);\n}\n\nexport function validateId(id: string): void {\n validateKey('id', id);\n}\n\nexport function validatePayloadSize(data: unknown, maxBytes: number): void {\n measureAndCheckSize(data, maxBytes);\n}\n\n/**\n * Measure the serialized size of `data` and throw if it exceeds `maxBytes`.\n * Returns the serialized form so callers can pass it to `db.query` without re-stringifying.\n */\nfunction measureAndCheckSize(data: unknown, maxBytes: number): string {\n const serialized = JSON.stringify(data) ?? '';\n const bytes = Buffer.byteLength(serialized, 'utf8');\n if (bytes > maxBytes) {\n throw new StateError(\n 'PAYLOAD_TOO_LARGE',\n `Document is ${bytes} bytes; exceeds limit of ${maxBytes} bytes. Split the document or raise maxDocumentBytes.`\n );\n }\n return serialized;\n}\n\n/**\n * Validate collection + id + payload size. Returns the serialized payload so\n * callers (e.g., PostgresStateStore) can reuse it without re-stringifying.\n */\nexport function validateWrite(collection: string, id: string, data: unknown, maxBytes: number): string {\n validateKey('collection', collection);\n validateKey('id', id);\n return measureAndCheckSize(data, maxBytes);\n}\n\n// ---------------------------------------------------------------------------\n// Interface\n// ---------------------------------------------------------------------------\n\nexport interface ListOptions {\n /** Filter by field values (exact match). */\n filter?: Record<string, unknown>;\n /** Maximum items to return. */\n limit?: number;\n /** Cursor from a previous list call. */\n cursor?: string;\n}\n\nexport interface ListResult<T = Record<string, unknown>> {\n items: T[];\n nextCursor?: string;\n}\n\n/**\n * Document and its row version, returned by {@link AdcpStateStore.getWithVersion}.\n *\n * `version` is a monotonically increasing integer that starts at `1` on first\n * write and increments by `1` on every `put`/`patch`/`putIfMatch`. Use it with\n * `putIfMatch` to implement optimistic concurrency.\n */\nexport interface VersionedDocument<T = Record<string, unknown>> {\n data: T;\n version: number;\n}\n\n/**\n * Result of an optimistic-concurrency write. Split on `ok` — success gives you\n * the new row version; failure gives you the current version the store has on\n * disk (or `null` if the row doesn't exist) so you can re-read, re-compute, and retry.\n *\n * **Conflict semantics**: `currentVersion` is a best-effort snapshot of the row\n * at conflict-report time, which may be later than the exact moment the CAS\n * failed — another writer can slip in between the failed write and the follow-up\n * read. This is fine for the retry loop in {@link patchWithRetry} (which just\n * re-reads anyway). Direct callers using `currentVersion` for anything beyond\n * \"retry if it changed\" should account for that race.\n */\nexport type PutIfMatchResult = { ok: true; version: number } | { ok: false; currentVersion: number | null };\n\n/**\n * Generic document store for AdCP domain objects.\n *\n * Collections are logical groupings (e.g., 'media_buys', 'accounts', 'creatives').\n * Each document is identified by collection + id.\n */\nexport interface AdcpStateStore {\n /** Get a document by collection and id. Returns null if not found. */\n get<T extends Record<string, unknown> = Record<string, unknown>>(collection: string, id: string): Promise<T | null>;\n\n /** Create or replace a document (upsert semantics). */\n put(collection: string, id: string, data: Record<string, unknown>): Promise<void>;\n\n /**\n * Merge fields into an existing document. Creates the document if it doesn't exist.\n * Only top-level fields are merged — nested objects are replaced, not deep-merged.\n */\n patch(collection: string, id: string, partial: Record<string, unknown>): Promise<void>;\n\n /** Delete a document. Returns true if it existed. */\n delete(collection: string, id: string): Promise<boolean>;\n\n /** List documents in a collection with optional filtering and pagination. */\n list<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n options?: ListOptions\n ): Promise<ListResult<T>>;\n\n /**\n * Convenience method for built-in stores: returns a session-scoped view.\n * Optional on the interface so custom `AdcpStateStore` implementations\n * aren't forced to implement it — callers who need the wrapper on any\n * store should use {@link scopedStore} instead, which handles the fallback.\n */\n scoped?(sessionKey: string): AdcpStateStore;\n\n /**\n * Read a document with its current row version. Returns `null` if the row\n * doesn't exist. Optional on the interface — custom stores that don't\n * track versions don't have to implement it. Use {@link patchWithRetry} to\n * guard against read-modify-write races without calling this directly.\n */\n getWithVersion?<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<VersionedDocument<T> | null>;\n\n /**\n * Atomic compare-and-swap write. Succeeds only if the row's current version\n * equals `expectedVersion` (or if the row doesn't exist and `expectedVersion`\n * is `null`). On conflict, returns the version the store actually has so the\n * caller can re-read and retry.\n *\n * Optional on the interface — custom stores that can't implement CAS don't\n * have to. Use {@link patchWithRetry} for the common \"update a field with\n * retry on conflict\" case.\n */\n putIfMatch?(\n collection: string,\n id: string,\n data: Record<string, unknown>,\n expectedVersion: number | null\n ): Promise<PutIfMatchResult>;\n}\n\n/**\n * Return a session-scoped view of any `AdcpStateStore`.\n *\n * Prefers `store.scoped(sessionKey)` when the store defines it; otherwise\n * wraps with {@link createSessionedStore}. Use this in SDK code and skills\n * so custom store implementations work without requiring them to implement\n * `scoped` themselves.\n *\n * ```ts\n * import { scopedStore } from '@adcp/sdk/server';\n *\n * const sessionStore = scopedStore(ctx.store, ctx.sessionKey!);\n * await sessionStore.put('media_buys', buyId, buy);\n * const { items } = await sessionStore.list('media_buys');\n * ```\n */\nexport function scopedStore(store: AdcpStateStore, sessionKey: string): AdcpStateStore {\n return store.scoped ? store.scoped(sessionKey) : createSessionedStore(store, sessionKey);\n}\n\n// ---------------------------------------------------------------------------\n// InMemoryStateStore\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_PAGE_SIZE = 50;\nconst MAX_PAGE_SIZE = 500;\n\nexport interface InMemoryStateStoreOptions {\n /** Max bytes per document. Defaults to {@link DEFAULT_MAX_DOCUMENT_BYTES}. */\n maxDocumentBytes?: number;\n}\n\ninterface VersionedRow {\n data: Record<string, unknown>;\n version: number;\n}\n\n/**\n * In-memory state store for development and testing.\n *\n * State is lost when the process restarts. Use PostgresStateStore for production.\n */\nexport class InMemoryStateStore implements AdcpStateStore {\n private collections = new Map<string, Map<string, VersionedRow>>();\n private readonly maxDocumentBytes: number;\n\n constructor(options?: InMemoryStateStoreOptions) {\n this.maxDocumentBytes = options?.maxDocumentBytes ?? DEFAULT_MAX_DOCUMENT_BYTES;\n }\n\n private getCollection(collection: string): Map<string, VersionedRow> {\n let col = this.collections.get(collection);\n if (!col) {\n col = new Map();\n this.collections.set(collection, col);\n }\n return col;\n }\n\n async get<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<T | null> {\n validateCollection(collection);\n validateId(id);\n const row = this.getCollection(collection).get(id);\n return row ? ({ ...row.data } as T) : null;\n }\n\n async getWithVersion<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<VersionedDocument<T> | null> {\n validateCollection(collection);\n validateId(id);\n const row = this.getCollection(collection).get(id);\n return row ? { data: { ...row.data } as T, version: row.version } : null;\n }\n\n async put(collection: string, id: string, data: Record<string, unknown>): Promise<void> {\n validateWrite(collection, id, data, this.maxDocumentBytes);\n const col = this.getCollection(collection);\n const existing = col.get(id);\n col.set(id, { data: { ...data }, version: (existing?.version ?? 0) + 1 });\n }\n\n async putIfMatch(\n collection: string,\n id: string,\n data: Record<string, unknown>,\n expectedVersion: number | null\n ): Promise<PutIfMatchResult> {\n validateWrite(collection, id, data, this.maxDocumentBytes);\n const col = this.getCollection(collection);\n const existing = col.get(id);\n const currentVersion = existing?.version ?? null;\n if (currentVersion !== expectedVersion) {\n return { ok: false, currentVersion };\n }\n const nextVersion = (existing?.version ?? 0) + 1;\n col.set(id, { data: { ...data }, version: nextVersion });\n return { ok: true, version: nextVersion };\n }\n\n async patch(collection: string, id: string, partial: Record<string, unknown>): Promise<void> {\n validateWrite(collection, id, partial, this.maxDocumentBytes);\n const col = this.getCollection(collection);\n const existing = col.get(id);\n col.set(id, {\n data: { ...(existing?.data ?? {}), ...partial },\n version: (existing?.version ?? 0) + 1,\n });\n }\n\n async delete(collection: string, id: string): Promise<boolean> {\n validateCollection(collection);\n validateId(id);\n return this.getCollection(collection).delete(id);\n }\n\n async list<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n options?: ListOptions\n ): Promise<ListResult<T>> {\n validateCollection(collection);\n const col = this.getCollection(collection);\n\n let entries = [...col.entries()].map(([id, row]) => ({ id, data: row.data as T }));\n\n if (options?.filter) {\n for (const [key, value] of Object.entries(options.filter)) {\n entries = entries.filter(e => e.data[key] === value);\n }\n }\n\n if (options?.cursor) {\n const idx = entries.findIndex(e => e.id === options.cursor);\n if (idx >= 0) {\n entries = entries.slice(idx + 1);\n }\n }\n\n const limit = Math.min(options?.limit ?? DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);\n const hasMore = entries.length > limit;\n entries = entries.slice(0, limit);\n\n const nextCursor = hasMore && entries.length > 0 ? entries[entries.length - 1]!.id : undefined;\n\n return { items: entries.map(e => ({ ...e.data })), nextCursor };\n }\n\n /** Clear all data. Useful in tests. */\n clear(): void {\n this.collections.clear();\n }\n\n /** Get the number of documents in a collection. */\n size(collection: string): number {\n return this.getCollection(collection).size;\n }\n\n scoped(sessionKey: string): AdcpStateStore {\n return createSessionedStore(this, sessionKey);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Sessioned store wrapper\n// ---------------------------------------------------------------------------\n\n/**\n * Marker field injected by {@link createSessionedStore} into every document\n * it writes. Sellers reading the underlying store directly will see it.\n */\nexport const SESSION_KEY_FIELD = '_session_key';\n\n/** Reserved scope-path separator. `:` is forbidden in sessionKeys and ids so `::` is unambiguous. */\nconst SESSION_ID_SEPARATOR = '::';\n\nfunction validateSessionPart(kind: 'sessionKey' | 'id', value: string): void {\n if (typeof value !== 'string' || !SESSION_KEY_PATTERN.test(value)) {\n throw new StateError(\n 'INVALID_ID',\n `${kind} \"${safeForMessage(value)}\" is invalid. Use ${SESSION_KEY_DESCRIPTION}.`\n );\n }\n}\n\nfunction stripSessionKey<T extends Record<string, unknown>>(doc: T | null): T | null {\n if (doc == null) return null;\n if (!(SESSION_KEY_FIELD in doc)) return doc;\n const { [SESSION_KEY_FIELD]: _ignored, ...rest } = doc as Record<string, unknown>;\n return rest as T;\n}\n\nfunction rejectReservedField(data: Record<string, unknown>): void {\n if (SESSION_KEY_FIELD in data) {\n throw new StateError(\n 'INVALID_ID',\n `Payload field \"${SESSION_KEY_FIELD}\" is reserved by the sessioned store. Rename it in your document.`\n );\n }\n}\n\n/**\n * Wrap an AdcpStateStore so every operation is isolated to `sessionKey`.\n *\n * - **ids** are prefixed with `${sessionKey}::` before hitting the underlying store.\n * - **writes** inject `_session_key: sessionKey` into the document so `list()` can filter on it.\n * - **reads/lists** strip `_session_key` before returning documents.\n * - **list filters** always AND-in `_session_key = sessionKey`.\n *\n * `sessionKey` and caller `id`s must match {@link SESSION_KEY_PATTERN} — no `:`\n * characters — so `${sessionKey}::${id}` is unambiguous. Payloads may not include\n * the reserved `_session_key` field.\n *\n * Use this when every handler's state is scoped to a tenant/brand/session,\n * so you don't have to thread `sessionKey` through every `put`/`list` call.\n */\nexport function createSessionedStore(inner: AdcpStateStore, sessionKey: string): AdcpStateStore {\n validateSessionPart('sessionKey', sessionKey);\n\n const prefix = (id: string) => {\n validateSessionPart('id', id);\n return `${sessionKey}${SESSION_ID_SEPARATOR}${id}`;\n };\n\n return {\n async get<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<T | null> {\n const doc = await inner.get<T>(collection, prefix(id));\n return stripSessionKey(doc);\n },\n\n async put(collection, id, data) {\n rejectReservedField(data);\n await inner.put(collection, prefix(id), { ...data, [SESSION_KEY_FIELD]: sessionKey });\n },\n\n async patch(collection, id, partial) {\n rejectReservedField(partial);\n await inner.patch(collection, prefix(id), { ...partial, [SESSION_KEY_FIELD]: sessionKey });\n },\n\n async delete(collection, id) {\n return inner.delete(collection, prefix(id));\n },\n\n async list<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n options?: ListOptions\n ): Promise<ListResult<T>> {\n const mergedFilter = {\n ...(options?.filter ?? {}),\n [SESSION_KEY_FIELD]: sessionKey,\n };\n const { items, nextCursor } = await inner.list<T>(collection, {\n ...options,\n filter: mergedFilter,\n });\n const stripped = items.map(item => stripSessionKey(item) as T);\n return nextCursor !== undefined ? { items: stripped, nextCursor } : { items: stripped };\n },\n\n // Proxy optimistic-concurrency methods when the inner store supports them.\n // Capture method references at wrap time (bound to `inner`) so runtime\n // reassignment or `this`-sensitive implementations like PostgresStateStore\n // can't desync.\n ...(() => {\n const innerGetWithVersion = inner.getWithVersion?.bind(inner);\n const innerPutIfMatch = inner.putIfMatch?.bind(inner);\n return {\n ...(innerGetWithVersion && {\n async getWithVersion<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<VersionedDocument<T> | null> {\n const result = await innerGetWithVersion<T>(collection, prefix(id));\n if (result == null) return null;\n const stripped = stripSessionKey(result.data);\n return stripped == null ? null : { data: stripped as T, version: result.version };\n },\n }),\n ...(innerPutIfMatch && {\n async putIfMatch(\n collection: string,\n id: string,\n data: Record<string, unknown>,\n expectedVersion: number | null\n ): Promise<PutIfMatchResult> {\n rejectReservedField(data);\n return innerPutIfMatch(\n collection,\n prefix(id),\n { ...data, [SESSION_KEY_FIELD]: sessionKey },\n expectedVersion\n );\n },\n }),\n };\n })(),\n };\n}\n\n// ---------------------------------------------------------------------------\n// patchWithRetry helper\n// ---------------------------------------------------------------------------\n\nexport interface PatchWithRetryOptions {\n /** Max retry attempts on version conflict. Defaults to 5. */\n maxAttempts?: number;\n\n /**\n * Called to compute a millisecond delay before the next attempt. Receives the\n * attempt number that just failed (1-indexed). Defaults to jittered exponential\n * backoff: `Math.random() * (1 << attempt)` (0–2 ms after 1, 0–4 ms after 2, …).\n * Return `0` (or pass a function that does) to disable backoff.\n */\n backoffMs?: (attempt: number) => number;\n\n /**\n * When the row is deleted between the initial read and the write, `patchWithRetry`\n * normally aborts with `PatchConflictError` to avoid silently resurrecting a\n * deleted document. Set to `true` to treat the post-delete state as a fresh\n * insert (re-running `update(null)` and inserting the result).\n *\n * Default: `false`.\n */\n allowResurrection?: boolean;\n}\n\n// Cap the shift so `1 << attempt` can't overflow to 0 or flip sign at attempt >= 31.\n// 20 is plenty: 2^20 = ~1 second, and maxAttempts would be absurd long before then.\nconst defaultBackoffMs = (attempt: number) => Math.random() * Math.pow(2, Math.min(attempt, 20));\n\n/**\n * Error thrown when `patchWithRetry` exceeds `maxAttempts` consecutive version conflicts,\n * or when the row was deleted between the initial read and the write and\n * `allowResurrection` is not set.\n */\nexport class PatchConflictError extends ADCPError {\n readonly code = 'PATCH_CONFLICT';\n constructor(\n readonly collection: string,\n readonly id: string,\n readonly attempts: number,\n readonly reason: 'max_attempts_exceeded' | 'deleted_during_retry',\n readonly lastObservedVersion: number | null\n ) {\n super(\n reason === 'deleted_during_retry'\n ? `patchWithRetry(${collection}, ${id}): row was deleted between read and write. ` +\n `Pass {allowResurrection: true} if you want to re-insert it.`\n : `patchWithRetry(${collection}, ${id}) exhausted ${attempts} attempts after version conflicts ` +\n `(last observed version: ${lastObservedVersion ?? 'none'}). ` +\n `Either the row has too many concurrent writers (split it), or raise {maxAttempts: N}.`\n );\n }\n}\n\n/**\n * Type guard for the conflict arm of {@link PutIfMatchResult}. Useful for\n * narrowing in hand-rolled retry loops.\n *\n * ```ts\n * const result = await store.putIfMatch('col', 'x', data, version);\n * if (isPutIfMatchConflict(result)) {\n * // result.currentVersion is number | null here\n * }\n * ```\n */\nexport function isPutIfMatchConflict(result: PutIfMatchResult): result is { ok: false; currentVersion: number | null } {\n return result.ok === false;\n}\n\n/**\n * Read-compute-write loop that retries on version conflict, using `getWithVersion`\n * + `putIfMatch` under the hood. The right primitive for counter-like updates\n * where two handlers might read the same pre-state and otherwise lose one write.\n *\n * `update` receives the current document (or `null` if the row doesn't exist)\n * and returns the next document. Returning `null` aborts without writing.\n *\n * ```ts\n * await patchWithRetry(ctx.store, 'media_buys', 'mb_1', (current) => ({\n * ...(current ?? {}),\n * budget_spent: (current?.budget_spent ?? 0) + cost,\n * }));\n * ```\n *\n * Throws {@link PatchConflictError} after `maxAttempts` consecutive conflicts.\n * Throws {@link PatchConflictError} with `reason: 'deleted_during_retry'` if\n * the row is deleted between the initial read and the write (opt into\n * resurrection via `allowResurrection: true`).\n *\n * Requires the store to implement both `getWithVersion` and `putIfMatch`.\n *\n * **Mutation caveat**: always build a fresh object in `update` — never mutate\n * the `current` argument in place. In-memory stores hand out a shallow copy\n * (nested references shared across retries) while Postgres deserializes JSONB\n * fresh each time; the safe pattern (`{ ...current, field: newValue }`) works\n * on both.\n *\n * **Error propagation**: if `update` throws, the exception propagates\n * immediately and no retry happens.\n *\n * **Backoff**: default is jittered exponential (low single-digit ms). Override\n * with `options.backoffMs`. Return `0` to disable.\n *\n * **Size**: each retry re-reads the full document. Avoid on rows close to\n * `maxDocumentBytes` — split into per-entity rows instead.\n */\nexport async function patchWithRetry<T extends Record<string, unknown> = Record<string, unknown>>(\n store: AdcpStateStore,\n collection: string,\n id: string,\n update: (current: T | null) => T | null,\n options: PatchWithRetryOptions = {}\n): Promise<T | null> {\n if (!store.getWithVersion || !store.putIfMatch) {\n throw new StateError(\n 'BACKEND_ERROR',\n 'patchWithRetry requires a store with getWithVersion and putIfMatch. Use InMemoryStateStore or PostgresStateStore, or pass a custom store that implements both.'\n );\n }\n\n const maxAttempts = options.maxAttempts ?? 5;\n const backoffMs = options.backoffMs ?? defaultBackoffMs;\n const allowResurrection = options.allowResurrection ?? false;\n\n let sawExistingRow = false;\n let lastObservedVersion: number | null = null;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const current = await store.getWithVersion<T>(collection, id);\n if (current) {\n sawExistingRow = true;\n lastObservedVersion = current.version;\n } else if (sawExistingRow && !allowResurrection) {\n throw new PatchConflictError(collection, id, attempt, 'deleted_during_retry', lastObservedVersion);\n }\n\n const nextData = update(current ? current.data : null);\n if (nextData === null) return null;\n\n const result = await store.putIfMatch(collection, id, nextData, current ? current.version : null);\n if (result.ok) return nextData;\n\n if (result.currentVersion !== null) lastObservedVersion = result.currentVersion;\n\n if (attempt < maxAttempts) {\n const delay = backoffMs(attempt);\n if (delay > 0) await new Promise(r => setTimeout(r, delay));\n }\n }\n throw new PatchConflictError(collection, id, maxAttempts, 'max_attempts_exceeded', lastObservedVersion);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
function isEnvelope(value) {
|
|
8
2
|
if (typeof value !== "object" || value === null) return false;
|
|
9
3
|
const o = value;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/server/structured-serialize.ts"],"sourcesContent":["/**\n * Lossless serialization of rich JS types through {@link AdcpStateStore}.\n *\n * AdcpStateStore accepts `Record<string, unknown>` and round-trips through\n * JSON, which silently drops `Map`, `Set`, and converts `Date` to string.\n * Handlers that keep those types in memory can wrap reads and writes:\n *\n * ```ts\n * import { structuredSerialize, structuredDeserialize } from '@adcp/sdk/server';\n *\n * await ctx.store.put('sessions', id, structuredSerialize(session));\n * const session = structuredDeserialize(await ctx.store.get('sessions', id));\n * ```\n *\n * Tagged envelopes use the namespaced field `__adcpType` to avoid collision\n * with domain data. Unknown tag values pass through unchanged on deserialize,\n * so a future tag addition won't corrupt caller data that already uses\n * `__adcpType` for something else.\n */\n\ntype Primitive = string | number | boolean | null;\n\ninterface DateEnvelope {\n __adcpType: 'Date';\n value: string;\n}\n\ninterface MapEnvelope {\n __adcpType: 'Map';\n entries: [unknown, unknown][];\n}\n\ninterface SetEnvelope {\n __adcpType: 'Set';\n values: unknown[];\n}\n\ntype Envelope = DateEnvelope | MapEnvelope | SetEnvelope;\n\nfunction isEnvelope(value: unknown): value is Envelope {\n if (typeof value !== 'object' || value === null) return false;\n const o = value as Record<string, unknown>;\n switch (o.__adcpType) {\n case 'Date':\n return typeof o.value === 'string';\n case 'Map':\n return Array.isArray(o.entries);\n case 'Set':\n return Array.isArray(o.values);\n default:\n return false;\n }\n}\n\n/**\n * Walk `value` replacing `Map`, `Set`, and `Date` instances with JSON-safe\n * tagged envelopes. Plain objects and arrays recurse.\n */\nexport function structuredSerialize(value: unknown): unknown {\n if (value === null || value === undefined) return value;\n const t = typeof value;\n if (t === 'string' || t === 'number' || t === 'boolean') return value as Primitive;\n\n if (value instanceof Date) {\n return { __adcpType: 'Date', value: value.toISOString() } satisfies DateEnvelope;\n }\n\n if (value instanceof Map) {\n return {\n __adcpType: 'Map',\n entries: [...value.entries()].map(([k, v]) => [structuredSerialize(k), structuredSerialize(v)]),\n } satisfies MapEnvelope;\n }\n\n if (value instanceof Set) {\n return {\n __adcpType: 'Set',\n values: [...value.values()].map(v => structuredSerialize(v)),\n } satisfies SetEnvelope;\n }\n\n if (Array.isArray(value)) {\n return value.map(v => structuredSerialize(v));\n }\n\n if (t === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value as Record<string, unknown>)) {\n out[key] = structuredSerialize(v);\n }\n return out;\n }\n\n // Functions, symbols, bigints — drop silently (consistent with JSON.stringify).\n return undefined;\n}\n\n/**\n * Inverse of {@link structuredSerialize}. Walks `value` converting tagged\n * envelopes back into native `Map`, `Set`, and `Date` instances.\n */\nexport function structuredDeserialize(value: unknown): unknown {\n if (value === null || value === undefined) return value;\n const t = typeof value;\n if (t === 'string' || t === 'number' || t === 'boolean') return value;\n\n if (Array.isArray(value)) {\n return value.map(v => structuredDeserialize(v));\n }\n\n if (isEnvelope(value)) {\n switch (value.__adcpType) {\n case 'Date':\n return new Date(value.value);\n case 'Map':\n return new Map(value.entries.map(([k, v]) => [structuredDeserialize(k), structuredDeserialize(v)]));\n case 'Set':\n return new Set(value.values.map(v => structuredDeserialize(v)));\n }\n }\n\n if (t === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value as Record<string, unknown>)) {\n out[key] = structuredDeserialize(v);\n }\n return out;\n }\n\n return value;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/server/structured-serialize.ts"],"sourcesContent":["/**\n * Lossless serialization of rich JS types through {@link AdcpStateStore}.\n *\n * AdcpStateStore accepts `Record<string, unknown>` and round-trips through\n * JSON, which silently drops `Map`, `Set`, and converts `Date` to string.\n * Handlers that keep those types in memory can wrap reads and writes:\n *\n * ```ts\n * import { structuredSerialize, structuredDeserialize } from '@adcp/sdk/server';\n *\n * await ctx.store.put('sessions', id, structuredSerialize(session));\n * const session = structuredDeserialize(await ctx.store.get('sessions', id));\n * ```\n *\n * Tagged envelopes use the namespaced field `__adcpType` to avoid collision\n * with domain data. Unknown tag values pass through unchanged on deserialize,\n * so a future tag addition won't corrupt caller data that already uses\n * `__adcpType` for something else.\n */\n\ntype Primitive = string | number | boolean | null;\n\ninterface DateEnvelope {\n __adcpType: 'Date';\n value: string;\n}\n\ninterface MapEnvelope {\n __adcpType: 'Map';\n entries: [unknown, unknown][];\n}\n\ninterface SetEnvelope {\n __adcpType: 'Set';\n values: unknown[];\n}\n\ntype Envelope = DateEnvelope | MapEnvelope | SetEnvelope;\n\nfunction isEnvelope(value: unknown): value is Envelope {\n if (typeof value !== 'object' || value === null) return false;\n const o = value as Record<string, unknown>;\n switch (o.__adcpType) {\n case 'Date':\n return typeof o.value === 'string';\n case 'Map':\n return Array.isArray(o.entries);\n case 'Set':\n return Array.isArray(o.values);\n default:\n return false;\n }\n}\n\n/**\n * Walk `value` replacing `Map`, `Set`, and `Date` instances with JSON-safe\n * tagged envelopes. Plain objects and arrays recurse.\n */\nexport function structuredSerialize(value: unknown): unknown {\n if (value === null || value === undefined) return value;\n const t = typeof value;\n if (t === 'string' || t === 'number' || t === 'boolean') return value as Primitive;\n\n if (value instanceof Date) {\n return { __adcpType: 'Date', value: value.toISOString() } satisfies DateEnvelope;\n }\n\n if (value instanceof Map) {\n return {\n __adcpType: 'Map',\n entries: [...value.entries()].map(([k, v]) => [structuredSerialize(k), structuredSerialize(v)]),\n } satisfies MapEnvelope;\n }\n\n if (value instanceof Set) {\n return {\n __adcpType: 'Set',\n values: [...value.values()].map(v => structuredSerialize(v)),\n } satisfies SetEnvelope;\n }\n\n if (Array.isArray(value)) {\n return value.map(v => structuredSerialize(v));\n }\n\n if (t === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value as Record<string, unknown>)) {\n out[key] = structuredSerialize(v);\n }\n return out;\n }\n\n // Functions, symbols, bigints — drop silently (consistent with JSON.stringify).\n return undefined;\n}\n\n/**\n * Inverse of {@link structuredSerialize}. Walks `value` converting tagged\n * envelopes back into native `Map`, `Set`, and `Date` instances.\n */\nexport function structuredDeserialize(value: unknown): unknown {\n if (value === null || value === undefined) return value;\n const t = typeof value;\n if (t === 'string' || t === 'number' || t === 'boolean') return value;\n\n if (Array.isArray(value)) {\n return value.map(v => structuredDeserialize(v));\n }\n\n if (isEnvelope(value)) {\n switch (value.__adcpType) {\n case 'Date':\n return new Date(value.value);\n case 'Map':\n return new Map(value.entries.map(([k, v]) => [structuredDeserialize(k), structuredDeserialize(v)]));\n case 'Set':\n return new Set(value.values.map(v => structuredDeserialize(v)));\n }\n }\n\n if (t === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value as Record<string, unknown>)) {\n out[key] = structuredDeserialize(v);\n }\n return out;\n }\n\n return value;\n}\n"],"mappings":"AAuCA,SAAS,WAAW,OAAmC;AACrD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,IAAI;AACV,UAAQ,EAAE,YAAY;AAAA,IACpB,KAAK;AACH,aAAO,OAAO,EAAE,UAAU;AAAA,IAC5B,KAAK;AACH,aAAO,MAAM,QAAQ,EAAE,OAAO;AAAA,IAChC,KAAK;AACH,aAAO,MAAM,QAAQ,EAAE,MAAM;AAAA,IAC/B;AACE,aAAO;AAAA,EACX;AACF;AAMO,SAAS,oBAAoB,OAAyB;AAC3D,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,QAAM,IAAI,OAAO;AACjB,MAAI,MAAM,YAAY,MAAM,YAAY,MAAM,UAAW,QAAO;AAEhE,MAAI,iBAAiB,MAAM;AACzB,WAAO,EAAE,YAAY,QAAQ,OAAO,MAAM,YAAY,EAAE;AAAA,EAC1D;AAEA,MAAI,iBAAiB,KAAK;AACxB,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,SAAS,CAAC,GAAG,MAAM,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC;AAAA,IAChG;AAAA,EACF;AAEA,MAAI,iBAAiB,KAAK;AACxB,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,EAAE,IAAI,OAAK,oBAAoB,CAAC,CAAC;AAAA,IAC7D;AAAA,EACF;AAEA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,OAAK,oBAAoB,CAAC,CAAC;AAAA,EAC9C;AAEA,MAAI,MAAM,UAAU;AAClB,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,KAAK,CAAC,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACvE,UAAI,GAAG,IAAI,oBAAoB,CAAC;AAAA,IAClC;AACA,WAAO;AAAA,EACT;AAGA,SAAO;AACT;AAMO,SAAS,sBAAsB,OAAyB;AAC7D,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,QAAM,IAAI,OAAO;AACjB,MAAI,MAAM,YAAY,MAAM,YAAY,MAAM,UAAW,QAAO;AAEhE,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,OAAK,sBAAsB,CAAC,CAAC;AAAA,EAChD;AAEA,MAAI,WAAW,KAAK,GAAG;AACrB,YAAQ,MAAM,YAAY;AAAA,MACxB,KAAK;AACH,eAAO,IAAI,KAAK,MAAM,KAAK;AAAA,MAC7B,KAAK;AACH,eAAO,IAAI,IAAI,MAAM,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,sBAAsB,CAAC,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;AAAA,MACpG,KAAK;AACH,eAAO,IAAI,IAAI,MAAM,OAAO,IAAI,OAAK,sBAAsB,CAAC,CAAC,CAAC;AAAA,IAClE;AAAA,EACF;AAEA,MAAI,MAAM,UAAU;AAClB,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,KAAK,CAAC,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACvE,UAAI,GAAG,IAAI,sBAAsB,CAAC;AAAA,IACpC;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
import { createHash } from "node:crypto";
|
|
8
2
|
import { lookup as dnsLookup } from "node:dns/promises";
|
|
9
3
|
import { callMCPTool } from "../protocols/mcp.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/server/targeting-helpers.ts"],"sourcesContent":["/**\n * Inventory list targeting helpers for AdCP sellers.\n *\n * AdCP 3.0 carries property and collection targeting as references to\n * externally-managed lists (`PropertyListReference`, `CollectionListReference`).\n * The seller resolves those references at serve time and filters its own\n * inventory against the resolved contents.\n *\n * These helpers let a seller handler do that in one line:\n *\n * @example\n * ```typescript\n * import { resolvePropertyList, matchesPropertyList } from '@adcp/sdk/server';\n *\n * if (targeting.property_list) {\n * const list = await resolvePropertyList(targeting.property_list);\n * inventory = inventory.filter(p => matchesPropertyList(p.identifier, list));\n * }\n * ```\n *\n * Resolution goes through MCP (`get_property_list` / `get_collection_list`) on\n * the referenced agent — the same contract a buyer agent uses to fetch the list.\n * Matching follows the identifier and distribution-id semantics defined by the\n * AdCP property and collection specs.\n */\n\nimport { createHash } from 'node:crypto';\nimport { lookup as dnsLookup } from 'node:dns/promises';\nimport { callMCPTool } from '../protocols/mcp';\nimport { isAlwaysBlocked, isPrivateIp } from '../net';\nimport { isInternalProbesAllowed } from '../utils/probe-policy';\nimport { createPinAndBindFetch } from './pin-and-bind-fetch';\nimport type {\n PropertyListReference,\n CollectionListReference,\n GetPropertyListResponse,\n GetCollectionListResponse,\n Identifier,\n} from '../types/tools.generated';\n\n// ---------------------------------------------------------------------------\n// Resolved list shapes\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedPropertyList {\n listId: string;\n agentUrl: string;\n identifiers: Identifier[];\n cacheValidUntil?: string;\n}\n\n/** A collection entry as returned by get_collection_list. */\nexport type ResolvedCollection = NonNullable<GetCollectionListResponse['collections']>[number];\n\nexport interface ResolvedCollectionList {\n listId: string;\n agentUrl: string;\n collections: ResolvedCollection[];\n cacheValidUntil?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Resolved list cache\n// ---------------------------------------------------------------------------\n\nexport type ResolvedListKind = 'property' | 'collection';\nexport type ResolvedListCacheValue = ResolvedPropertyList | ResolvedCollectionList;\nexport const DEFAULT_RESOLVE_LIST_PAGE_SIZE = 1000;\n\nexport interface ResolvedListCacheEntry<TValue extends ResolvedListCacheValue = ResolvedListCacheValue> {\n value: TValue;\n expiresAtMs: number;\n}\n\nexport interface ResolvedListCache {\n get<TValue extends ResolvedListCacheValue>(key: string, nowMs?: number): TValue | undefined;\n set<TValue extends ResolvedListCacheValue>(key: string, entry: ResolvedListCacheEntry<TValue>): void;\n delete(key: string): boolean;\n clear(): void;\n}\n\nclass MemoryResolvedListCache implements ResolvedListCache {\n private readonly entries = new Map<string, ResolvedListCacheEntry>();\n\n get<TValue extends ResolvedListCacheValue>(key: string, nowMs = Date.now()): TValue | undefined {\n const entry = this.entries.get(key);\n if (!entry) return undefined;\n if (entry.expiresAtMs <= nowMs) {\n this.entries.delete(key);\n return undefined;\n }\n return cloneResolvedList(entry.value) as TValue;\n }\n\n set<TValue extends ResolvedListCacheValue>(key: string, entry: ResolvedListCacheEntry<TValue>): void {\n this.entries.set(key, {\n expiresAtMs: entry.expiresAtMs,\n value: cloneResolvedList(entry.value),\n });\n }\n\n delete(key: string): boolean {\n return this.entries.delete(key);\n }\n\n clear(): void {\n this.entries.clear();\n }\n}\n\nexport function createResolvedListCache(): ResolvedListCache {\n return new MemoryResolvedListCache();\n}\n\nexport const defaultResolvedListCache = createResolvedListCache();\n\nexport function clearDefaultResolvedListCache(): void {\n defaultResolvedListCache.clear();\n}\n\n// ---------------------------------------------------------------------------\n// resolvePropertyList / resolveCollectionList\n// ---------------------------------------------------------------------------\n\nexport type ResolveListCallTool = (\n agentUrl: string,\n toolName: 'get_property_list' | 'get_collection_list',\n args: Record<string, unknown>,\n authToken?: string\n) => Promise<unknown>;\n\nconst defaultResolveListFetchBase = createPinAndBindFetch();\nconst defaultResolveListFetch: typeof fetch = (input, init) =>\n defaultResolveListFetchBase(input, { ...init, redirect: 'manual' });\n\nconst defaultResolveListCallTool: ResolveListCallTool = (agentUrl, toolName, args, authToken) =>\n callMCPTool(agentUrl, toolName, args, authToken, [], undefined, undefined, defaultResolveListFetch);\n\nexport interface ResolveListOptions {\n /** Maximum page size when calling get_property_list / get_collection_list. Defaults to 1000. */\n pageSize?: number;\n /** Maximum number of pages to walk before treating pagination as unsafe. Defaults to 100. */\n maxPages?: number;\n /** Cache for resolved list contents. Defaults to the process-local SDK cache. Pass false to disable caching. */\n cache?: ResolvedListCache | false;\n /**\n * Tenant/principal/auth-context fingerprint for cache scoping when the list\n * reference does not carry an auth_token. Shared caching is disabled without\n * either auth_token or this explicit scope.\n */\n cacheScopeKey?: string;\n /** Clock hook for testing cache expiry. */\n now?: () => Date | number;\n /** MCP call hook for testing/custom transports. */\n callTool?: ResolveListCallTool;\n}\n\n/**\n * Resolve a PropertyListReference to the concrete identifiers it contains.\n *\n * Calls `get_property_list` on the referenced agent with `resolve: true`.\n * Honors `auth_token` on the reference if present.\n */\nexport async function resolvePropertyList(\n ref: PropertyListReference,\n options: ResolveListOptions = {}\n): Promise<ResolvedPropertyList> {\n const structurallyNormalizedRef = await normalizePropertyListReference(ref, { resolveDns: false });\n const cache = cacheForOptions(options);\n const nowMs = nowMsForOptions(options);\n const cacheKey = resolvedListCacheKey('property', structurallyNormalizedRef, options);\n const cached = cacheKey ? cache?.get<ResolvedPropertyList>(cacheKey, nowMs) : undefined;\n if (cached) return cached;\n\n const normalizedRef = options.callTool\n ? structurallyNormalizedRef\n : await normalizePropertyListReference(structurallyNormalizedRef, { resolveDns: false });\n const result = await fetchResolvedPropertyList(normalizedRef, options);\n cacheResolvedList(cache, cacheKey, result, nowMs);\n return result;\n}\n\nasync function fetchResolvedPropertyList(\n ref: PropertyListReference,\n options: ResolveListOptions\n): Promise<ResolvedPropertyList> {\n const callTool = options.callTool ?? defaultResolveListCallTool;\n const identifiers: Identifier[] = [];\n let listId: string;\n let cacheValidUntil: string | undefined;\n let missingCacheValidUntil = false;\n let cursor: string | undefined;\n\n for (let pageIndex = 0; pageIndex < maxPagesForOptions(options); pageIndex += 1) {\n const args = buildResolveListArgs(ref.list_id, pageSizeForOptions(options), cursor);\n\n const raw = (await callTool(ref.agent_url, 'get_property_list', args, ref.auth_token)) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object' || !('list' in raw)) {\n throw new Error('property_list_invalid_response');\n }\n const response = raw as unknown as GetPropertyListResponse;\n listId = response.list.list_id;\n identifiers.push(...(response.identifiers ?? []));\n if (typeof response.cache_valid_until === 'string') {\n cacheValidUntil = earliestIsoTimestamp(cacheValidUntil, response.cache_valid_until);\n } else {\n missingCacheValidUntil = true;\n }\n\n const pagination = readPagination(response.pagination);\n if (pagination.invalid) {\n throw new Error('property_list_invalid_pagination');\n }\n if (!pagination.hasMore) {\n return {\n listId,\n agentUrl: ref.agent_url,\n identifiers,\n cacheValidUntil: missingCacheValidUntil ? undefined : cacheValidUntil,\n };\n }\n if (!pagination.cursor) {\n throw new Error('property_list_invalid_pagination');\n }\n cursor = pagination.cursor;\n }\n\n throw new Error('property_list_pagination_limit_exceeded');\n}\n\n/**\n * Resolve a CollectionListReference to the concrete collections it contains.\n *\n * Calls `get_collection_list` on the referenced agent with `resolve: true`.\n * Honors `auth_token` on the reference if present.\n */\nexport async function resolveCollectionList(\n ref: CollectionListReference,\n options: ResolveListOptions = {}\n): Promise<ResolvedCollectionList> {\n const structurallyNormalizedRef = await normalizeCollectionListReference(ref, { resolveDns: false });\n const cache = cacheForOptions(options);\n const nowMs = nowMsForOptions(options);\n const cacheKey = resolvedListCacheKey('collection', structurallyNormalizedRef, options);\n const cached = cacheKey ? cache?.get<ResolvedCollectionList>(cacheKey, nowMs) : undefined;\n if (cached) return cached;\n\n const normalizedRef = options.callTool\n ? structurallyNormalizedRef\n : await normalizeCollectionListReference(structurallyNormalizedRef, { resolveDns: false });\n const result = await fetchResolvedCollectionList(normalizedRef, options);\n cacheResolvedList(cache, cacheKey, result, nowMs);\n return result;\n}\n\nasync function fetchResolvedCollectionList(\n ref: CollectionListReference,\n options: ResolveListOptions\n): Promise<ResolvedCollectionList> {\n const callTool = options.callTool ?? defaultResolveListCallTool;\n const collections: ResolvedCollection[] = [];\n let listId: string;\n let cacheValidUntil: string | undefined;\n let missingCacheValidUntil = false;\n let cursor: string | undefined;\n\n for (let pageIndex = 0; pageIndex < maxPagesForOptions(options); pageIndex += 1) {\n const args = buildResolveListArgs(ref.list_id, pageSizeForOptions(options), cursor);\n\n const raw = (await callTool(ref.agent_url, 'get_collection_list', args, ref.auth_token)) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object' || !('list' in raw)) {\n throw new Error('collection_list_invalid_response');\n }\n const response = raw as unknown as GetCollectionListResponse;\n listId = response.list.list_id;\n collections.push(...(response.collections ?? []));\n if (typeof response.cache_valid_until === 'string') {\n cacheValidUntil = earliestIsoTimestamp(cacheValidUntil, response.cache_valid_until);\n } else {\n missingCacheValidUntil = true;\n }\n\n const pagination = readPagination(response.pagination);\n if (pagination.invalid) {\n throw new Error('collection_list_invalid_pagination');\n }\n if (!pagination.hasMore) {\n return {\n listId,\n agentUrl: ref.agent_url,\n collections,\n cacheValidUntil: missingCacheValidUntil ? undefined : cacheValidUntil,\n };\n }\n if (!pagination.cursor) {\n throw new Error('collection_list_invalid_pagination');\n }\n cursor = pagination.cursor;\n }\n\n throw new Error('collection_list_pagination_limit_exceeded');\n}\n\nexport function resolvedListCacheKey(\n kind: ResolvedListKind,\n ref: Pick<PropertyListReference | CollectionListReference, 'agent_url' | 'list_id' | 'auth_token'>,\n options: Pick<ResolveListOptions, 'pageSize' | 'cacheScopeKey'> = {}\n): string | undefined {\n const scope = ref.auth_token ?? options.cacheScopeKey;\n if (!scope) return undefined;\n const material = JSON.stringify({\n kind,\n agent_url: ref.agent_url,\n list_id: ref.list_id,\n scope_sha256: sha256(scope),\n page_size: options.pageSize ?? DEFAULT_RESOLVE_LIST_PAGE_SIZE,\n resolve: true,\n });\n return `adcp-resolved-list:${sha256(material)}`;\n}\n\nasync function normalizePropertyListReference(\n ref: PropertyListReference,\n options: { resolveDns: boolean }\n): Promise<PropertyListReference> {\n return {\n ...ref,\n agent_url: await normalizeListAgentUrl(ref.agent_url, options),\n };\n}\n\nasync function normalizeCollectionListReference(\n ref: CollectionListReference,\n options: { resolveDns: boolean }\n): Promise<CollectionListReference> {\n return {\n ...ref,\n agent_url: await normalizeListAgentUrl(ref.agent_url, options),\n };\n}\n\nasync function normalizeListAgentUrl(raw: string, options: { resolveDns: boolean }): Promise<string> {\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new Error('list_agent_url_invalid');\n }\n\n if (url.username || url.password || url.search || url.hash) {\n throw new Error('list_agent_url_malformed');\n }\n\n const allowInternal = isInternalProbesAllowed();\n if (url.protocol !== 'https:' && !(allowInternal && url.protocol === 'http:')) {\n throw new Error('list_agent_url_insecure');\n }\n\n const hostname = url.hostname.replace(/^\\[|\\]$/g, '');\n if (isAlwaysBlocked(hostname)) {\n throw new Error('list_agent_url_always_blocked');\n }\n if (!allowInternal && isPrivateIp(hostname)) {\n throw new Error('list_agent_url_private_address');\n }\n\n if (options.resolveDns) {\n let addresses: { address: string }[];\n try {\n addresses = await dnsLookup(hostname, { all: true });\n } catch {\n throw new Error('list_agent_url_dns_failed');\n }\n if (addresses.length === 0) {\n throw new Error('list_agent_url_dns_empty');\n }\n for (const { address } of addresses) {\n if (isAlwaysBlocked(address)) {\n throw new Error('list_agent_url_always_blocked');\n }\n if (!allowInternal && isPrivateIp(address)) {\n throw new Error('list_agent_url_private_address');\n }\n }\n }\n\n return url.toString();\n}\n\nfunction buildResolveListArgs(listId: string, pageSize: number, cursor: string | undefined) {\n const args: Record<string, unknown> = {\n list_id: listId,\n resolve: true,\n };\n const pagination: Record<string, unknown> = {};\n pagination.max_results = pageSize;\n if (cursor) pagination.cursor = cursor;\n if (Object.keys(pagination).length > 0) args.pagination = pagination;\n return args;\n}\n\nfunction cacheForOptions(options: ResolveListOptions): ResolvedListCache | undefined {\n if (options.callTool && options.cache === undefined) return undefined;\n return options.cache === false ? undefined : (options.cache ?? defaultResolvedListCache);\n}\n\nfunction cacheResolvedList(\n cache: ResolvedListCache | undefined,\n cacheKey: string | undefined,\n value: ResolvedListCacheValue,\n nowMs: number\n): void {\n if (!cache || !cacheKey || !value.cacheValidUntil) return;\n const expiresAtMs = Date.parse(value.cacheValidUntil);\n if (!Number.isFinite(expiresAtMs) || expiresAtMs <= nowMs) return;\n cache.set(cacheKey, { value, expiresAtMs });\n}\n\nfunction nowMsForOptions(options: ResolveListOptions): number {\n const now = options.now?.();\n if (now instanceof Date) return now.getTime();\n if (typeof now === 'number') return now;\n return Date.now();\n}\n\nfunction maxPagesForOptions(options: ResolveListOptions): number {\n return options.maxPages ?? 100;\n}\n\nfunction pageSizeForOptions(options: Pick<ResolveListOptions, 'pageSize'>): number {\n return options.pageSize ?? DEFAULT_RESOLVE_LIST_PAGE_SIZE;\n}\n\nfunction readPagination(value: unknown): { hasMore: boolean; cursor?: string; invalid: boolean } {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return { hasMore: false, invalid: false };\n const pagination = value as { has_more?: unknown; cursor?: unknown };\n const cursor = typeof pagination.cursor === 'string' && pagination.cursor.length > 0 ? pagination.cursor : undefined;\n const invalid =\n (pagination.has_more !== undefined && typeof pagination.has_more !== 'boolean') ||\n (cursor !== undefined && pagination.has_more !== true);\n return {\n hasMore: pagination.has_more === true,\n cursor,\n invalid,\n };\n}\n\nfunction earliestIsoTimestamp(current: string | undefined, next: string): string {\n if (!current) return next;\n const currentMs = Date.parse(current);\n const nextMs = Date.parse(next);\n if (!Number.isFinite(currentMs)) return next;\n if (!Number.isFinite(nextMs)) return current;\n return nextMs < currentMs ? next : current;\n}\n\nfunction cloneResolvedList<TValue extends ResolvedListCacheValue>(value: TValue): TValue {\n return structuredClone(value);\n}\n\nfunction sha256(value: string): string {\n return createHash('sha256').update(value, 'utf8').digest('hex');\n}\n\n// ---------------------------------------------------------------------------\n// matchesPropertyList / matchesCollectionList\n// ---------------------------------------------------------------------------\n\n/**\n * Return true if `property` matches any identifier in the resolved list.\n *\n * Domain matching rules (from the AdCP property spec):\n * - Exact match on the identifier value is always accepted.\n * - A `domain` entry of `example.com` also matches `www.example.com` and\n * `m.example.com` — the two canonical aliases for a base domain.\n * - A `domain` entry of `*.example.com` matches every subdomain but NOT the\n * base domain itself.\n * - Non-domain identifier types (ios_bundle, network_id, etc.) use exact\n * string match on both `type` and `value`.\n */\nexport function matchesPropertyList(property: Identifier, list: ResolvedPropertyList): boolean {\n return list.identifiers.some(entry => identifiersMatch(property, entry));\n}\n\nfunction identifiersMatch(property: Identifier, entry: Identifier): boolean {\n if (property.type !== entry.type) return false;\n if (property.type !== 'domain') {\n return property.value === entry.value;\n }\n return domainMatches(property.value, entry.value);\n}\n\nfunction domainMatches(candidate: string, pattern: string): boolean {\n const c = candidate.toLowerCase();\n const p = pattern.toLowerCase();\n if (c === p) return true;\n if (p.startsWith('*.')) {\n const suffix = p.slice(1); // \".example.com\"\n return c.endsWith(suffix) && c !== p.slice(2);\n }\n return c === `www.${p}` || c === `m.${p}`;\n}\n\n/**\n * Return true if `collection` matches any entry in the resolved list.\n *\n * Matching modes:\n * - Collections match when `collection_rid` is set on both sides and equal.\n * - Otherwise, they match when they share at least one `distribution_ids`\n * entry with the same `type` and `value`.\n *\n * A collection with no collection_rid and no distribution_ids cannot match —\n * the seller has nothing to match against.\n */\nexport function matchesCollectionList(\n collection: { collection_rid?: string; distribution_ids?: { type: string; value: string }[] },\n list: ResolvedCollectionList\n): boolean {\n return list.collections.some(entry => collectionsMatch(collection, entry));\n}\n\nfunction collectionsMatch(\n a: { collection_rid?: string; distribution_ids?: { type: string; value: string }[] },\n b: ResolvedCollection\n): boolean {\n if (a.collection_rid && b.collection_rid && a.collection_rid === b.collection_rid) {\n return true;\n }\n if (!a.distribution_ids?.length || !b.distribution_ids?.length) return false;\n return a.distribution_ids.some(aid =>\n b.distribution_ids!.some(bid => aid.type === bid.type && aid.value === bid.value)\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/server/targeting-helpers.ts"],"sourcesContent":["/**\n * Inventory list targeting helpers for AdCP sellers.\n *\n * AdCP 3.0 carries property and collection targeting as references to\n * externally-managed lists (`PropertyListReference`, `CollectionListReference`).\n * The seller resolves those references at serve time and filters its own\n * inventory against the resolved contents.\n *\n * These helpers let a seller handler do that in one line:\n *\n * @example\n * ```typescript\n * import { resolvePropertyList, matchesPropertyList } from '@adcp/sdk/server';\n *\n * if (targeting.property_list) {\n * const list = await resolvePropertyList(targeting.property_list);\n * inventory = inventory.filter(p => matchesPropertyList(p.identifier, list));\n * }\n * ```\n *\n * Resolution goes through MCP (`get_property_list` / `get_collection_list`) on\n * the referenced agent — the same contract a buyer agent uses to fetch the list.\n * Matching follows the identifier and distribution-id semantics defined by the\n * AdCP property and collection specs.\n */\n\nimport { createHash } from 'node:crypto';\nimport { lookup as dnsLookup } from 'node:dns/promises';\nimport { callMCPTool } from '../protocols/mcp';\nimport { isAlwaysBlocked, isPrivateIp } from '../net';\nimport { isInternalProbesAllowed } from '../utils/probe-policy';\nimport { createPinAndBindFetch } from './pin-and-bind-fetch';\nimport type {\n PropertyListReference,\n CollectionListReference,\n GetPropertyListResponse,\n GetCollectionListResponse,\n Identifier,\n} from '../types/tools.generated';\n\n// ---------------------------------------------------------------------------\n// Resolved list shapes\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedPropertyList {\n listId: string;\n agentUrl: string;\n identifiers: Identifier[];\n cacheValidUntil?: string;\n}\n\n/** A collection entry as returned by get_collection_list. */\nexport type ResolvedCollection = NonNullable<GetCollectionListResponse['collections']>[number];\n\nexport interface ResolvedCollectionList {\n listId: string;\n agentUrl: string;\n collections: ResolvedCollection[];\n cacheValidUntil?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Resolved list cache\n// ---------------------------------------------------------------------------\n\nexport type ResolvedListKind = 'property' | 'collection';\nexport type ResolvedListCacheValue = ResolvedPropertyList | ResolvedCollectionList;\nexport const DEFAULT_RESOLVE_LIST_PAGE_SIZE = 1000;\n\nexport interface ResolvedListCacheEntry<TValue extends ResolvedListCacheValue = ResolvedListCacheValue> {\n value: TValue;\n expiresAtMs: number;\n}\n\nexport interface ResolvedListCache {\n get<TValue extends ResolvedListCacheValue>(key: string, nowMs?: number): TValue | undefined;\n set<TValue extends ResolvedListCacheValue>(key: string, entry: ResolvedListCacheEntry<TValue>): void;\n delete(key: string): boolean;\n clear(): void;\n}\n\nclass MemoryResolvedListCache implements ResolvedListCache {\n private readonly entries = new Map<string, ResolvedListCacheEntry>();\n\n get<TValue extends ResolvedListCacheValue>(key: string, nowMs = Date.now()): TValue | undefined {\n const entry = this.entries.get(key);\n if (!entry) return undefined;\n if (entry.expiresAtMs <= nowMs) {\n this.entries.delete(key);\n return undefined;\n }\n return cloneResolvedList(entry.value) as TValue;\n }\n\n set<TValue extends ResolvedListCacheValue>(key: string, entry: ResolvedListCacheEntry<TValue>): void {\n this.entries.set(key, {\n expiresAtMs: entry.expiresAtMs,\n value: cloneResolvedList(entry.value),\n });\n }\n\n delete(key: string): boolean {\n return this.entries.delete(key);\n }\n\n clear(): void {\n this.entries.clear();\n }\n}\n\nexport function createResolvedListCache(): ResolvedListCache {\n return new MemoryResolvedListCache();\n}\n\nexport const defaultResolvedListCache = createResolvedListCache();\n\nexport function clearDefaultResolvedListCache(): void {\n defaultResolvedListCache.clear();\n}\n\n// ---------------------------------------------------------------------------\n// resolvePropertyList / resolveCollectionList\n// ---------------------------------------------------------------------------\n\nexport type ResolveListCallTool = (\n agentUrl: string,\n toolName: 'get_property_list' | 'get_collection_list',\n args: Record<string, unknown>,\n authToken?: string\n) => Promise<unknown>;\n\nconst defaultResolveListFetchBase = createPinAndBindFetch();\nconst defaultResolveListFetch: typeof fetch = (input, init) =>\n defaultResolveListFetchBase(input, { ...init, redirect: 'manual' });\n\nconst defaultResolveListCallTool: ResolveListCallTool = (agentUrl, toolName, args, authToken) =>\n callMCPTool(agentUrl, toolName, args, authToken, [], undefined, undefined, defaultResolveListFetch);\n\nexport interface ResolveListOptions {\n /** Maximum page size when calling get_property_list / get_collection_list. Defaults to 1000. */\n pageSize?: number;\n /** Maximum number of pages to walk before treating pagination as unsafe. Defaults to 100. */\n maxPages?: number;\n /** Cache for resolved list contents. Defaults to the process-local SDK cache. Pass false to disable caching. */\n cache?: ResolvedListCache | false;\n /**\n * Tenant/principal/auth-context fingerprint for cache scoping when the list\n * reference does not carry an auth_token. Shared caching is disabled without\n * either auth_token or this explicit scope.\n */\n cacheScopeKey?: string;\n /** Clock hook for testing cache expiry. */\n now?: () => Date | number;\n /** MCP call hook for testing/custom transports. */\n callTool?: ResolveListCallTool;\n}\n\n/**\n * Resolve a PropertyListReference to the concrete identifiers it contains.\n *\n * Calls `get_property_list` on the referenced agent with `resolve: true`.\n * Honors `auth_token` on the reference if present.\n */\nexport async function resolvePropertyList(\n ref: PropertyListReference,\n options: ResolveListOptions = {}\n): Promise<ResolvedPropertyList> {\n const structurallyNormalizedRef = await normalizePropertyListReference(ref, { resolveDns: false });\n const cache = cacheForOptions(options);\n const nowMs = nowMsForOptions(options);\n const cacheKey = resolvedListCacheKey('property', structurallyNormalizedRef, options);\n const cached = cacheKey ? cache?.get<ResolvedPropertyList>(cacheKey, nowMs) : undefined;\n if (cached) return cached;\n\n const normalizedRef = options.callTool\n ? structurallyNormalizedRef\n : await normalizePropertyListReference(structurallyNormalizedRef, { resolveDns: false });\n const result = await fetchResolvedPropertyList(normalizedRef, options);\n cacheResolvedList(cache, cacheKey, result, nowMs);\n return result;\n}\n\nasync function fetchResolvedPropertyList(\n ref: PropertyListReference,\n options: ResolveListOptions\n): Promise<ResolvedPropertyList> {\n const callTool = options.callTool ?? defaultResolveListCallTool;\n const identifiers: Identifier[] = [];\n let listId: string;\n let cacheValidUntil: string | undefined;\n let missingCacheValidUntil = false;\n let cursor: string | undefined;\n\n for (let pageIndex = 0; pageIndex < maxPagesForOptions(options); pageIndex += 1) {\n const args = buildResolveListArgs(ref.list_id, pageSizeForOptions(options), cursor);\n\n const raw = (await callTool(ref.agent_url, 'get_property_list', args, ref.auth_token)) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object' || !('list' in raw)) {\n throw new Error('property_list_invalid_response');\n }\n const response = raw as unknown as GetPropertyListResponse;\n listId = response.list.list_id;\n identifiers.push(...(response.identifiers ?? []));\n if (typeof response.cache_valid_until === 'string') {\n cacheValidUntil = earliestIsoTimestamp(cacheValidUntil, response.cache_valid_until);\n } else {\n missingCacheValidUntil = true;\n }\n\n const pagination = readPagination(response.pagination);\n if (pagination.invalid) {\n throw new Error('property_list_invalid_pagination');\n }\n if (!pagination.hasMore) {\n return {\n listId,\n agentUrl: ref.agent_url,\n identifiers,\n cacheValidUntil: missingCacheValidUntil ? undefined : cacheValidUntil,\n };\n }\n if (!pagination.cursor) {\n throw new Error('property_list_invalid_pagination');\n }\n cursor = pagination.cursor;\n }\n\n throw new Error('property_list_pagination_limit_exceeded');\n}\n\n/**\n * Resolve a CollectionListReference to the concrete collections it contains.\n *\n * Calls `get_collection_list` on the referenced agent with `resolve: true`.\n * Honors `auth_token` on the reference if present.\n */\nexport async function resolveCollectionList(\n ref: CollectionListReference,\n options: ResolveListOptions = {}\n): Promise<ResolvedCollectionList> {\n const structurallyNormalizedRef = await normalizeCollectionListReference(ref, { resolveDns: false });\n const cache = cacheForOptions(options);\n const nowMs = nowMsForOptions(options);\n const cacheKey = resolvedListCacheKey('collection', structurallyNormalizedRef, options);\n const cached = cacheKey ? cache?.get<ResolvedCollectionList>(cacheKey, nowMs) : undefined;\n if (cached) return cached;\n\n const normalizedRef = options.callTool\n ? structurallyNormalizedRef\n : await normalizeCollectionListReference(structurallyNormalizedRef, { resolveDns: false });\n const result = await fetchResolvedCollectionList(normalizedRef, options);\n cacheResolvedList(cache, cacheKey, result, nowMs);\n return result;\n}\n\nasync function fetchResolvedCollectionList(\n ref: CollectionListReference,\n options: ResolveListOptions\n): Promise<ResolvedCollectionList> {\n const callTool = options.callTool ?? defaultResolveListCallTool;\n const collections: ResolvedCollection[] = [];\n let listId: string;\n let cacheValidUntil: string | undefined;\n let missingCacheValidUntil = false;\n let cursor: string | undefined;\n\n for (let pageIndex = 0; pageIndex < maxPagesForOptions(options); pageIndex += 1) {\n const args = buildResolveListArgs(ref.list_id, pageSizeForOptions(options), cursor);\n\n const raw = (await callTool(ref.agent_url, 'get_collection_list', args, ref.auth_token)) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object' || !('list' in raw)) {\n throw new Error('collection_list_invalid_response');\n }\n const response = raw as unknown as GetCollectionListResponse;\n listId = response.list.list_id;\n collections.push(...(response.collections ?? []));\n if (typeof response.cache_valid_until === 'string') {\n cacheValidUntil = earliestIsoTimestamp(cacheValidUntil, response.cache_valid_until);\n } else {\n missingCacheValidUntil = true;\n }\n\n const pagination = readPagination(response.pagination);\n if (pagination.invalid) {\n throw new Error('collection_list_invalid_pagination');\n }\n if (!pagination.hasMore) {\n return {\n listId,\n agentUrl: ref.agent_url,\n collections,\n cacheValidUntil: missingCacheValidUntil ? undefined : cacheValidUntil,\n };\n }\n if (!pagination.cursor) {\n throw new Error('collection_list_invalid_pagination');\n }\n cursor = pagination.cursor;\n }\n\n throw new Error('collection_list_pagination_limit_exceeded');\n}\n\nexport function resolvedListCacheKey(\n kind: ResolvedListKind,\n ref: Pick<PropertyListReference | CollectionListReference, 'agent_url' | 'list_id' | 'auth_token'>,\n options: Pick<ResolveListOptions, 'pageSize' | 'cacheScopeKey'> = {}\n): string | undefined {\n const scope = ref.auth_token ?? options.cacheScopeKey;\n if (!scope) return undefined;\n const material = JSON.stringify({\n kind,\n agent_url: ref.agent_url,\n list_id: ref.list_id,\n scope_sha256: sha256(scope),\n page_size: options.pageSize ?? DEFAULT_RESOLVE_LIST_PAGE_SIZE,\n resolve: true,\n });\n return `adcp-resolved-list:${sha256(material)}`;\n}\n\nasync function normalizePropertyListReference(\n ref: PropertyListReference,\n options: { resolveDns: boolean }\n): Promise<PropertyListReference> {\n return {\n ...ref,\n agent_url: await normalizeListAgentUrl(ref.agent_url, options),\n };\n}\n\nasync function normalizeCollectionListReference(\n ref: CollectionListReference,\n options: { resolveDns: boolean }\n): Promise<CollectionListReference> {\n return {\n ...ref,\n agent_url: await normalizeListAgentUrl(ref.agent_url, options),\n };\n}\n\nasync function normalizeListAgentUrl(raw: string, options: { resolveDns: boolean }): Promise<string> {\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new Error('list_agent_url_invalid');\n }\n\n if (url.username || url.password || url.search || url.hash) {\n throw new Error('list_agent_url_malformed');\n }\n\n const allowInternal = isInternalProbesAllowed();\n if (url.protocol !== 'https:' && !(allowInternal && url.protocol === 'http:')) {\n throw new Error('list_agent_url_insecure');\n }\n\n const hostname = url.hostname.replace(/^\\[|\\]$/g, '');\n if (isAlwaysBlocked(hostname)) {\n throw new Error('list_agent_url_always_blocked');\n }\n if (!allowInternal && isPrivateIp(hostname)) {\n throw new Error('list_agent_url_private_address');\n }\n\n if (options.resolveDns) {\n let addresses: { address: string }[];\n try {\n addresses = await dnsLookup(hostname, { all: true });\n } catch {\n throw new Error('list_agent_url_dns_failed');\n }\n if (addresses.length === 0) {\n throw new Error('list_agent_url_dns_empty');\n }\n for (const { address } of addresses) {\n if (isAlwaysBlocked(address)) {\n throw new Error('list_agent_url_always_blocked');\n }\n if (!allowInternal && isPrivateIp(address)) {\n throw new Error('list_agent_url_private_address');\n }\n }\n }\n\n return url.toString();\n}\n\nfunction buildResolveListArgs(listId: string, pageSize: number, cursor: string | undefined) {\n const args: Record<string, unknown> = {\n list_id: listId,\n resolve: true,\n };\n const pagination: Record<string, unknown> = {};\n pagination.max_results = pageSize;\n if (cursor) pagination.cursor = cursor;\n if (Object.keys(pagination).length > 0) args.pagination = pagination;\n return args;\n}\n\nfunction cacheForOptions(options: ResolveListOptions): ResolvedListCache | undefined {\n if (options.callTool && options.cache === undefined) return undefined;\n return options.cache === false ? undefined : (options.cache ?? defaultResolvedListCache);\n}\n\nfunction cacheResolvedList(\n cache: ResolvedListCache | undefined,\n cacheKey: string | undefined,\n value: ResolvedListCacheValue,\n nowMs: number\n): void {\n if (!cache || !cacheKey || !value.cacheValidUntil) return;\n const expiresAtMs = Date.parse(value.cacheValidUntil);\n if (!Number.isFinite(expiresAtMs) || expiresAtMs <= nowMs) return;\n cache.set(cacheKey, { value, expiresAtMs });\n}\n\nfunction nowMsForOptions(options: ResolveListOptions): number {\n const now = options.now?.();\n if (now instanceof Date) return now.getTime();\n if (typeof now === 'number') return now;\n return Date.now();\n}\n\nfunction maxPagesForOptions(options: ResolveListOptions): number {\n return options.maxPages ?? 100;\n}\n\nfunction pageSizeForOptions(options: Pick<ResolveListOptions, 'pageSize'>): number {\n return options.pageSize ?? DEFAULT_RESOLVE_LIST_PAGE_SIZE;\n}\n\nfunction readPagination(value: unknown): { hasMore: boolean; cursor?: string; invalid: boolean } {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return { hasMore: false, invalid: false };\n const pagination = value as { has_more?: unknown; cursor?: unknown };\n const cursor = typeof pagination.cursor === 'string' && pagination.cursor.length > 0 ? pagination.cursor : undefined;\n const invalid =\n (pagination.has_more !== undefined && typeof pagination.has_more !== 'boolean') ||\n (cursor !== undefined && pagination.has_more !== true);\n return {\n hasMore: pagination.has_more === true,\n cursor,\n invalid,\n };\n}\n\nfunction earliestIsoTimestamp(current: string | undefined, next: string): string {\n if (!current) return next;\n const currentMs = Date.parse(current);\n const nextMs = Date.parse(next);\n if (!Number.isFinite(currentMs)) return next;\n if (!Number.isFinite(nextMs)) return current;\n return nextMs < currentMs ? next : current;\n}\n\nfunction cloneResolvedList<TValue extends ResolvedListCacheValue>(value: TValue): TValue {\n return structuredClone(value);\n}\n\nfunction sha256(value: string): string {\n return createHash('sha256').update(value, 'utf8').digest('hex');\n}\n\n// ---------------------------------------------------------------------------\n// matchesPropertyList / matchesCollectionList\n// ---------------------------------------------------------------------------\n\n/**\n * Return true if `property` matches any identifier in the resolved list.\n *\n * Domain matching rules (from the AdCP property spec):\n * - Exact match on the identifier value is always accepted.\n * - A `domain` entry of `example.com` also matches `www.example.com` and\n * `m.example.com` — the two canonical aliases for a base domain.\n * - A `domain` entry of `*.example.com` matches every subdomain but NOT the\n * base domain itself.\n * - Non-domain identifier types (ios_bundle, network_id, etc.) use exact\n * string match on both `type` and `value`.\n */\nexport function matchesPropertyList(property: Identifier, list: ResolvedPropertyList): boolean {\n return list.identifiers.some(entry => identifiersMatch(property, entry));\n}\n\nfunction identifiersMatch(property: Identifier, entry: Identifier): boolean {\n if (property.type !== entry.type) return false;\n if (property.type !== 'domain') {\n return property.value === entry.value;\n }\n return domainMatches(property.value, entry.value);\n}\n\nfunction domainMatches(candidate: string, pattern: string): boolean {\n const c = candidate.toLowerCase();\n const p = pattern.toLowerCase();\n if (c === p) return true;\n if (p.startsWith('*.')) {\n const suffix = p.slice(1); // \".example.com\"\n return c.endsWith(suffix) && c !== p.slice(2);\n }\n return c === `www.${p}` || c === `m.${p}`;\n}\n\n/**\n * Return true if `collection` matches any entry in the resolved list.\n *\n * Matching modes:\n * - Collections match when `collection_rid` is set on both sides and equal.\n * - Otherwise, they match when they share at least one `distribution_ids`\n * entry with the same `type` and `value`.\n *\n * A collection with no collection_rid and no distribution_ids cannot match —\n * the seller has nothing to match against.\n */\nexport function matchesCollectionList(\n collection: { collection_rid?: string; distribution_ids?: { type: string; value: string }[] },\n list: ResolvedCollectionList\n): boolean {\n return list.collections.some(entry => collectionsMatch(collection, entry));\n}\n\nfunction collectionsMatch(\n a: { collection_rid?: string; distribution_ids?: { type: string; value: string }[] },\n b: ResolvedCollection\n): boolean {\n if (a.collection_rid && b.collection_rid && a.collection_rid === b.collection_rid) {\n return true;\n }\n if (!a.distribution_ids?.length || !b.distribution_ids?.length) return false;\n return a.distribution_ids.some(aid =>\n b.distribution_ids!.some(bid => aid.type === bid.type && aid.value === bid.value)\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
2
|
import { getSdkServer } from "./adcp-server.mjs";
|
|
9
3
|
import { InMemoryTaskStore as _InMemoryTaskStore } from "@modelcontextprotocol/sdk/experimental/tasks/stores/in-memory.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/server/tasks.ts"],"sourcesContent":["/**\n * Server-side helpers for MCP Tasks protocol support.\n *\n * Publishers can use these to add async task support to their AdCP MCP servers.\n * The MCP SDK handles all protocol plumbing (tasks/get, tasks/result, tasks/cancel,\n * tasks/list, TTL, _meta injection) — publishers only implement task creation and\n * result storage logic.\n *\n * @example\n * ```typescript\n * import { createTaskCapableServer, registerAdcpTaskTool, InMemoryTaskStore } from '@adcp/sdk';\n *\n * const server = createTaskCapableServer('My Publisher', '1.0.0');\n *\n * registerAdcpTaskTool(server, 'create_media_buy', {\n * description: 'Create a media buy (async)',\n * inputSchema: { campaign_name: z.string() },\n * taskSupport: 'required',\n * }, {\n * createTask: async (args, extra) => {\n * const task = await extra.taskStore.createTask({ ttl: 300_000 });\n * startBackgroundWork(task.taskId, args);\n * return { task };\n * },\n * getTask: async (_args, extra) => {\n * return extra.taskStore.getTask(extra.taskId);\n * },\n * getTaskResult: async (_args, extra) => {\n * return extra.taskStore.getTaskResult(extra.taskId);\n * },\n * });\n * ```\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { AdcpServer } from './adcp-server';\nimport { getSdkServer } from './adcp-server';\nimport type { RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ZodRawShapeCompat, AnySchema } from '@modelcontextprotocol/sdk/server/zod-compat.js';\nimport type { ToolAnnotations, CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolTaskHandler, TaskToolExecution } from '@modelcontextprotocol/sdk/experimental/tasks/interfaces.js';\n\n// Re-export SDK task primitives so publishers don't import from experimental paths\nimport { InMemoryTaskStore as _InMemoryTaskStore } from '@modelcontextprotocol/sdk/experimental/tasks/stores/in-memory.js';\nexport { _InMemoryTaskStore as InMemoryTaskStore };\nexport { isTerminal } from '@modelcontextprotocol/sdk/experimental/tasks/interfaces.js';\nexport type {\n TaskStore,\n TaskMessageQueue,\n CreateTaskOptions,\n ToolTaskHandler,\n CreateTaskRequestHandlerExtra,\n TaskRequestHandlerExtra,\n} from '@modelcontextprotocol/sdk/experimental/tasks/interfaces.js';\nexport type { CreateTaskResult, GetTaskResult, Task } from '@modelcontextprotocol/sdk/experimental/tasks/types.js';\n\n/**\n * Build a task tool result response.\n *\n * Same pattern as `productsResponse()` / `mediaBuyResponse()` but designed for\n * use in `getTaskResult` handlers where you return the final async result.\n */\nexport function taskToolResponse(data: Record<string, unknown>, summary?: string): CallToolResult {\n return {\n content: [{ type: 'text', text: summary ?? 'Task completed' }],\n structuredContent: data,\n };\n}\n\n/**\n * Configuration for registering an AdCP task tool.\n */\nexport interface AdcpTaskToolConfig {\n description: string;\n title?: string;\n inputSchema?: ZodRawShapeCompat | AnySchema;\n outputSchema?: ZodRawShapeCompat | AnySchema;\n annotations?: ToolAnnotations;\n taskSupport?: 'optional' | 'required';\n}\n\n/**\n * Register an AdCP task-based tool on an MCP server.\n *\n * Wraps `server.experimental.tasks.registerToolTask()` with AdCP defaults.\n * Sets `execution.taskSupport` (default: 'optional') and passes through to the SDK.\n *\n * Accepts either an `AdcpServer` from `createAdcpServer()` or a raw SDK\n * `McpServer` from `createTaskCapableServer()` — the helper unwraps the\n * opaque handle when needed so registration reaches the SDK server.\n */\nexport function registerAdcpTaskTool(\n server: AdcpServer | McpServer,\n name: string,\n config: AdcpTaskToolConfig,\n handler: ToolTaskHandler<any>\n): RegisteredTool {\n const mcp = getSdkServer(server as AdcpServer) ?? (server as McpServer);\n const { description, title, inputSchema, outputSchema, annotations, taskSupport = 'optional' } = config;\n\n const execution: TaskToolExecution = { taskSupport };\n\n const sdkConfig = {\n description,\n execution,\n ...(title != null && { title }),\n ...(outputSchema != null && { outputSchema }),\n ...(annotations != null && { annotations }),\n };\n\n if (inputSchema != null) {\n return mcp.experimental.tasks.registerToolTask(name, { ...sdkConfig, inputSchema }, handler);\n }\n\n return mcp.experimental.tasks.registerToolTask(\n name,\n sdkConfig as Parameters<typeof mcp.experimental.tasks.registerToolTask>[1],\n handler as ToolTaskHandler<undefined>\n );\n}\n\n/**\n * Create an MCP server with task support pre-configured.\n *\n * Sets up the server with a `taskStore` (defaults to `InMemoryTaskStore`) and\n * declares tasks capability. Publishers can then use `registerAdcpTaskTool()`\n * or `server.experimental.tasks.registerToolTask()` directly.\n *\n * This uses the higher-level `McpServer` API. Publishers with complex dispatch\n * patterns (e.g., custom request routing) can use the lower-level `Server` class\n * directly by passing `taskStore` in `ServerOptions` and using `setRequestHandler`\n * for task lifecycle methods. See the MCP SDK docs for that approach.\n */\nexport function createTaskCapableServer(\n name: string,\n version: string,\n options?: {\n taskStore?: import('@modelcontextprotocol/sdk/experimental/tasks/interfaces.js').TaskStore;\n taskMessageQueue?: import('@modelcontextprotocol/sdk/experimental/tasks/interfaces.js').TaskMessageQueue;\n instructions?: string;\n }\n): McpServer {\n const taskStore = options?.taskStore ?? new _InMemoryTaskStore();\n\n return new McpServer({ name, version }, {\n capabilities: {\n tasks: {\n list: {},\n cancel: {},\n requests: {\n tools: {\n call: {},\n },\n },\n },\n },\n taskStore,\n taskMessageQueue: options?.taskMessageQueue,\n instructions: options?.instructions,\n } as ConstructorParameters<typeof McpServer>[1]);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/server/tasks.ts"],"sourcesContent":["/**\n * Server-side helpers for MCP Tasks protocol support.\n *\n * Publishers can use these to add async task support to their AdCP MCP servers.\n * The MCP SDK handles all protocol plumbing (tasks/get, tasks/result, tasks/cancel,\n * tasks/list, TTL, _meta injection) — publishers only implement task creation and\n * result storage logic.\n *\n * @example\n * ```typescript\n * import { createTaskCapableServer, registerAdcpTaskTool, InMemoryTaskStore } from '@adcp/sdk';\n *\n * const server = createTaskCapableServer('My Publisher', '1.0.0');\n *\n * registerAdcpTaskTool(server, 'create_media_buy', {\n * description: 'Create a media buy (async)',\n * inputSchema: { campaign_name: z.string() },\n * taskSupport: 'required',\n * }, {\n * createTask: async (args, extra) => {\n * const task = await extra.taskStore.createTask({ ttl: 300_000 });\n * startBackgroundWork(task.taskId, args);\n * return { task };\n * },\n * getTask: async (_args, extra) => {\n * return extra.taskStore.getTask(extra.taskId);\n * },\n * getTaskResult: async (_args, extra) => {\n * return extra.taskStore.getTaskResult(extra.taskId);\n * },\n * });\n * ```\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { AdcpServer } from './adcp-server';\nimport { getSdkServer } from './adcp-server';\nimport type { RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ZodRawShapeCompat, AnySchema } from '@modelcontextprotocol/sdk/server/zod-compat.js';\nimport type { ToolAnnotations, CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolTaskHandler, TaskToolExecution } from '@modelcontextprotocol/sdk/experimental/tasks/interfaces.js';\n\n// Re-export SDK task primitives so publishers don't import from experimental paths\nimport { InMemoryTaskStore as _InMemoryTaskStore } from '@modelcontextprotocol/sdk/experimental/tasks/stores/in-memory.js';\nexport { _InMemoryTaskStore as InMemoryTaskStore };\nexport { isTerminal } from '@modelcontextprotocol/sdk/experimental/tasks/interfaces.js';\nexport type {\n TaskStore,\n TaskMessageQueue,\n CreateTaskOptions,\n ToolTaskHandler,\n CreateTaskRequestHandlerExtra,\n TaskRequestHandlerExtra,\n} from '@modelcontextprotocol/sdk/experimental/tasks/interfaces.js';\nexport type { CreateTaskResult, GetTaskResult, Task } from '@modelcontextprotocol/sdk/experimental/tasks/types.js';\n\n/**\n * Build a task tool result response.\n *\n * Same pattern as `productsResponse()` / `mediaBuyResponse()` but designed for\n * use in `getTaskResult` handlers where you return the final async result.\n */\nexport function taskToolResponse(data: Record<string, unknown>, summary?: string): CallToolResult {\n return {\n content: [{ type: 'text', text: summary ?? 'Task completed' }],\n structuredContent: data,\n };\n}\n\n/**\n * Configuration for registering an AdCP task tool.\n */\nexport interface AdcpTaskToolConfig {\n description: string;\n title?: string;\n inputSchema?: ZodRawShapeCompat | AnySchema;\n outputSchema?: ZodRawShapeCompat | AnySchema;\n annotations?: ToolAnnotations;\n taskSupport?: 'optional' | 'required';\n}\n\n/**\n * Register an AdCP task-based tool on an MCP server.\n *\n * Wraps `server.experimental.tasks.registerToolTask()` with AdCP defaults.\n * Sets `execution.taskSupport` (default: 'optional') and passes through to the SDK.\n *\n * Accepts either an `AdcpServer` from `createAdcpServer()` or a raw SDK\n * `McpServer` from `createTaskCapableServer()` — the helper unwraps the\n * opaque handle when needed so registration reaches the SDK server.\n */\nexport function registerAdcpTaskTool(\n server: AdcpServer | McpServer,\n name: string,\n config: AdcpTaskToolConfig,\n handler: ToolTaskHandler<any>\n): RegisteredTool {\n const mcp = getSdkServer(server as AdcpServer) ?? (server as McpServer);\n const { description, title, inputSchema, outputSchema, annotations, taskSupport = 'optional' } = config;\n\n const execution: TaskToolExecution = { taskSupport };\n\n const sdkConfig = {\n description,\n execution,\n ...(title != null && { title }),\n ...(outputSchema != null && { outputSchema }),\n ...(annotations != null && { annotations }),\n };\n\n if (inputSchema != null) {\n return mcp.experimental.tasks.registerToolTask(name, { ...sdkConfig, inputSchema }, handler);\n }\n\n return mcp.experimental.tasks.registerToolTask(\n name,\n sdkConfig as Parameters<typeof mcp.experimental.tasks.registerToolTask>[1],\n handler as ToolTaskHandler<undefined>\n );\n}\n\n/**\n * Create an MCP server with task support pre-configured.\n *\n * Sets up the server with a `taskStore` (defaults to `InMemoryTaskStore`) and\n * declares tasks capability. Publishers can then use `registerAdcpTaskTool()`\n * or `server.experimental.tasks.registerToolTask()` directly.\n *\n * This uses the higher-level `McpServer` API. Publishers with complex dispatch\n * patterns (e.g., custom request routing) can use the lower-level `Server` class\n * directly by passing `taskStore` in `ServerOptions` and using `setRequestHandler`\n * for task lifecycle methods. See the MCP SDK docs for that approach.\n */\nexport function createTaskCapableServer(\n name: string,\n version: string,\n options?: {\n taskStore?: import('@modelcontextprotocol/sdk/experimental/tasks/interfaces.js').TaskStore;\n taskMessageQueue?: import('@modelcontextprotocol/sdk/experimental/tasks/interfaces.js').TaskMessageQueue;\n instructions?: string;\n }\n): McpServer {\n const taskStore = options?.taskStore ?? new _InMemoryTaskStore();\n\n return new McpServer({ name, version }, {\n capabilities: {\n tasks: {\n list: {},\n cancel: {},\n requests: {\n tools: {\n call: {},\n },\n },\n },\n },\n taskStore,\n taskMessageQueue: options?.taskMessageQueue,\n instructions: options?.instructions,\n } as ConstructorParameters<typeof McpServer>[1]);\n}\n"],"mappings":"AAkCA,SAAS,iBAAiB;AAE1B,SAAS,oBAAoB;AAO7B,SAAS,qBAAqB,0BAA0B;AAExD,SAAS,kBAAkB;AAiBpB,SAAS,iBAAiB,MAA+B,SAAkC;AAChG,SAAO;AAAA,IACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,WAAW,iBAAiB,CAAC;AAAA,IAC7D,mBAAmB;AAAA,EACrB;AACF;AAwBO,SAAS,qBACd,QACA,MACA,QACA,SACgB;AAChB,QAAM,MAAM,aAAa,MAAoB,KAAM;AACnD,QAAM,EAAE,aAAa,OAAO,aAAa,cAAc,aAAa,cAAc,WAAW,IAAI;AAEjG,QAAM,YAA+B,EAAE,YAAY;AAEnD,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,IACA,GAAI,SAAS,QAAQ,EAAE,MAAM;AAAA,IAC7B,GAAI,gBAAgB,QAAQ,EAAE,aAAa;AAAA,IAC3C,GAAI,eAAe,QAAQ,EAAE,YAAY;AAAA,EAC3C;AAEA,MAAI,eAAe,MAAM;AACvB,WAAO,IAAI,aAAa,MAAM,iBAAiB,MAAM,EAAE,GAAG,WAAW,YAAY,GAAG,OAAO;AAAA,EAC7F;AAEA,SAAO,IAAI,aAAa,MAAM;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAcO,SAAS,wBACd,MACA,SACA,SAKW;AACX,QAAM,YAAY,SAAS,aAAa,IAAI,mBAAmB;AAE/D,SAAO,IAAI,UAAU,EAAE,MAAM,QAAQ,GAAG;AAAA,IACtC,cAAc;AAAA,MACZ,OAAO;AAAA,QACL,MAAM,CAAC;AAAA,QACP,QAAQ,CAAC;AAAA,QACT,UAAU;AAAA,UACR,OAAO;AAAA,YACL,MAAM,CAAC;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,IACA,kBAAkB,SAAS;AAAA,IAC3B,cAAc,SAAS;AAAA,EACzB,CAA+C;AACjD;","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
import { mergeSeedProduct } from "../testing/seed-merge.mjs";
|
|
8
2
|
function isSandboxRequest(input) {
|
|
9
3
|
const account = input.account;
|