@adcp/sdk 17.0.0-beta.1 → 17.0.0-beta.2
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/keyed-account-store.js +1 -1
- package/dist/lib/adapters/keyed-account-store.mjs +1 -1
- package/dist/lib/adapters/version/3.0/brand-fields.d.mts +7 -1
- package/dist/lib/adapters/version/3.0/brand-fields.d.ts +7 -1
- package/dist/lib/adapters/version/3.0/brand-fields.js +139 -3
- package/dist/lib/adapters/version/3.0/brand-fields.mjs +136 -2
- package/dist/lib/adapters/version/3.0/index.js +6 -0
- package/dist/lib/adapters/version/3.0/index.mjs +7 -1
- package/dist/lib/adapters/version/types.d.mts +5 -0
- package/dist/lib/adapters/version/types.d.ts +5 -0
- package/dist/lib/canonical-references/index.js +2 -0
- package/dist/lib/canonical-references/index.mjs +2 -0
- package/dist/lib/client/account-changes.d.mts +3 -1
- package/dist/lib/client/account-changes.d.ts +3 -1
- package/dist/lib/client/account-changes.js +22 -2
- package/dist/lib/client/account-changes.mjs +22 -2
- package/dist/lib/conformance/oracle.js +3 -2
- package/dist/lib/conformance/oracle.mjs +3 -2
- package/dist/lib/core/AgentClient.d.mts +165 -1
- package/dist/lib/core/AgentClient.d.ts +165 -1
- package/dist/lib/core/AgentClient.js +446 -8
- package/dist/lib/core/AgentClient.mjs +446 -8
- package/dist/lib/core/ConversationTypes.d.mts +8 -0
- package/dist/lib/core/ConversationTypes.d.ts +8 -0
- package/dist/lib/core/ProtocolResponseParser.d.mts +1 -1
- package/dist/lib/core/ProtocolResponseParser.d.ts +1 -1
- package/dist/lib/core/ProtocolResponseParser.js +28 -18
- package/dist/lib/core/ProtocolResponseParser.mjs +11 -1
- package/dist/lib/core/SingleAgentClient.d.mts +115 -2
- package/dist/lib/core/SingleAgentClient.d.ts +115 -2
- package/dist/lib/core/SingleAgentClient.js +547 -67
- package/dist/lib/core/SingleAgentClient.mjs +534 -54
- package/dist/lib/core/TaskExecutor.d.mts +7 -0
- package/dist/lib/core/TaskExecutor.d.ts +7 -0
- package/dist/lib/core/TaskExecutor.js +18 -5
- package/dist/lib/core/TaskExecutor.mjs +18 -5
- package/dist/lib/core/task-status.d.mts +2 -0
- package/dist/lib/core/task-status.d.ts +2 -0
- package/dist/lib/core/task-status.js +11 -2
- package/dist/lib/core/task-status.mjs +9 -1
- package/dist/lib/identity-3.3/trust.d.mts +1 -4
- package/dist/lib/identity-3.3/trust.d.ts +1 -4
- package/dist/lib/identity-3.3/trust.js +34 -21
- package/dist/lib/identity-3.3/trust.mjs +34 -21
- package/dist/lib/identity-3.3/validation.js +5 -3
- package/dist/lib/identity-3.3/validation.mjs +6 -4
- package/dist/lib/index.d.mts +6 -52
- package/dist/lib/index.d.ts +6 -52
- package/dist/lib/index.js +11 -0
- package/dist/lib/index.mjs +7 -0
- package/dist/lib/media-buy/compatibility.js +6 -1
- package/dist/lib/media-buy/compatibility.mjs +6 -1
- package/dist/lib/protocols/mcp-scope.d.mts +3 -0
- package/dist/lib/protocols/mcp-scope.d.ts +3 -0
- package/dist/lib/protocols/mcp-scope.js +8 -3
- package/dist/lib/protocols/mcp-scope.mjs +8 -3
- package/dist/lib/reporting/inspection.js +1 -0
- package/dist/lib/reporting/inspection.mjs +1 -0
- package/dist/lib/reporting/ledger/coverage.d.mts +5 -0
- package/dist/lib/reporting/ledger/coverage.d.ts +5 -0
- package/dist/lib/reporting/ledger/coverage.js +37 -3
- package/dist/lib/reporting/ledger/coverage.mjs +36 -3
- package/dist/lib/reporting/ledger/handler.js +7 -4
- package/dist/lib/reporting/ledger/handler.mjs +7 -4
- package/dist/lib/reporting/ledger/producer.js +215 -69
- package/dist/lib/reporting/ledger/producer.mjs +217 -70
- package/dist/lib/reporting/ledger/schedule.d.mts +2 -2
- package/dist/lib/reporting/ledger/schedule.d.ts +2 -2
- package/dist/lib/reporting/ledger/schedule.js +8 -5
- package/dist/lib/reporting/ledger/schedule.mjs +8 -5
- package/dist/lib/reporting/ledger/status-ingest.d.mts +1 -1
- package/dist/lib/reporting/ledger/status-ingest.d.ts +1 -1
- package/dist/lib/reporting/ledger/status-ingest.js +4 -3
- package/dist/lib/reporting/ledger/status-ingest.mjs +4 -3
- package/dist/lib/reporting/ledger/types.d.mts +36 -1
- package/dist/lib/reporting/ledger/types.d.ts +36 -1
- package/dist/lib/reporting/service/index.d.mts +14 -1
- package/dist/lib/reporting/service/index.d.ts +14 -1
- package/dist/lib/reporting/service/index.js +24 -12
- package/dist/lib/reporting/service/index.mjs +24 -12
- package/dist/lib/schemas/browser.d.mts +2 -0
- package/dist/lib/schemas/browser.d.ts +2 -0
- package/dist/lib/schemas/browser.js +3 -0
- package/dist/lib/schemas/browser.mjs +2 -0
- package/dist/lib/schemas/index.d.mts +5 -3
- package/dist/lib/schemas/index.d.ts +5 -3
- package/dist/lib/schemas/index.js +5 -0
- package/dist/lib/schemas/index.mjs +4 -0
- package/dist/lib/server/account-response-identity.d.mts +17 -0
- package/dist/lib/server/account-response-identity.d.ts +17 -0
- package/dist/lib/server/account-response-identity.js +52 -0
- package/dist/lib/server/account-response-identity.mjs +28 -0
- package/dist/lib/server/account-sync-contract.js +2 -2
- package/dist/lib/server/account-sync-contract.mjs +2 -2
- package/dist/lib/server/create-adcp-server.js +33 -20
- package/dist/lib/server/create-adcp-server.mjs +36 -12
- package/dist/lib/server/decisioning/account.d.mts +36 -10
- package/dist/lib/server/decisioning/account.d.ts +36 -10
- package/dist/lib/server/decisioning/account.js +33 -14
- package/dist/lib/server/decisioning/account.mjs +33 -14
- package/dist/lib/server/decisioning/runtime/from-platform.d.mts +5 -5
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +5 -5
- package/dist/lib/server/decisioning/runtime/from-platform.js +4 -4
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +4 -4
- package/dist/lib/server/media-buy-store.d.mts +26 -12
- package/dist/lib/server/media-buy-store.d.ts +26 -12
- package/dist/lib/server/media-buy-store.js +69 -21
- package/dist/lib/server/media-buy-store.mjs +69 -21
- package/dist/lib/server/notification-subscriptions/runtime.d.mts +1 -1
- package/dist/lib/server/notification-subscriptions/runtime.d.ts +1 -1
- package/dist/lib/server/notification-subscriptions/runtime.js +4 -0
- package/dist/lib/server/notification-subscriptions/runtime.mjs +4 -0
- package/dist/lib/server/responses.js +9 -1
- package/dist/lib/server/responses.mjs +9 -1
- package/dist/lib/signing/agent-fetch.d.mts +1 -1
- package/dist/lib/signing/agent-fetch.d.ts +1 -1
- package/dist/lib/signing/agent-fetch.js +3 -3
- package/dist/lib/signing/agent-fetch.mjs +3 -3
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.js +60 -14
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +60 -14
- package/dist/lib/testing/storyboard/compliance.d.mts +2 -5
- package/dist/lib/testing/storyboard/compliance.d.ts +2 -5
- package/dist/lib/testing/storyboard/compliance.js +62 -13
- package/dist/lib/testing/storyboard/compliance.mjs +63 -14
- package/dist/lib/testing/storyboard/request-signing/vector-loader.d.mts +2 -0
- package/dist/lib/testing/storyboard/request-signing/vector-loader.d.ts +2 -0
- package/dist/lib/testing/storyboard/request-signing/vector-loader.js +11 -0
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +10 -0
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/types/accept-proposal.d.ts +20 -28
- package/dist/lib/types/asset-instances.d.mts +1 -1
- package/dist/lib/types/asset-instances.d.ts +1 -1
- package/dist/lib/types/buy-products.d.ts +20 -28
- package/dist/lib/types/check-governance.d.ts +20 -28
- package/dist/lib/types/comply-test-controller.d.ts +20 -28
- package/dist/lib/types/control-media-buy.d.ts +20 -28
- package/dist/lib/types/core.generated.d.mts +273 -184
- package/dist/lib/types/core.generated.d.ts +273 -184
- package/dist/lib/types/create-media-buy.d.ts +20 -28
- package/dist/lib/types/get-media-buys.d.ts +20 -28
- package/dist/lib/types/get-products.d.ts +20 -28
- package/dist/lib/types/index.d.mts +6 -1
- package/dist/lib/types/index.d.ts +6 -1
- package/dist/lib/types/index.js +6 -1
- package/dist/lib/types/index.mjs +4 -1
- package/dist/lib/types/inline-enums.generated.d.mts +30 -4
- package/dist/lib/types/inline-enums.generated.d.ts +30 -4
- package/dist/lib/types/inline-enums.generated.js +41 -2
- package/dist/lib/types/inline-enums.generated.mjs +28 -2
- package/dist/lib/types/list-products.d.ts +20 -28
- package/dist/lib/types/list-proposals.d.ts +20 -28
- package/dist/lib/types/media-buy-delivery-report.d.mts +6 -0
- package/dist/lib/types/media-buy-delivery-report.d.ts +6 -0
- package/dist/lib/types/media-buy-delivery-report.js +16 -0
- package/dist/lib/types/media-buy-delivery-report.mjs +0 -0
- package/dist/lib/types/refine-proposals.d.ts +20 -28
- package/dist/lib/types/request-proposals.d.ts +20 -28
- package/dist/lib/types/schemas.generated.d.ts +63113 -127273
- package/dist/lib/types/schemas.generated.js +759 -770
- package/dist/lib/types/schemas.generated.mjs +759 -770
- package/dist/lib/types/targeting-keys.generated.d.mts +4 -0
- package/dist/lib/types/targeting-keys.generated.d.ts +4 -0
- package/dist/lib/types/targeting-keys.generated.js +109 -0
- package/dist/lib/types/targeting-keys.generated.mjs +84 -0
- package/dist/lib/types/tools.generated.d.mts +2 -68
- package/dist/lib/types/tools.generated.d.ts +2 -68
- package/dist/lib/types/update-media-buy.d.ts +20 -28
- package/dist/lib/utils/adcp-version-config.js +5 -2
- package/dist/lib/utils/adcp-version-config.mjs +5 -2
- package/dist/lib/utils/response-unwrapper.js +6 -1
- package/dist/lib/utils/response-unwrapper.mjs +6 -1
- package/dist/lib/v2/format-schema/resolver.js +1 -1
- package/dist/lib/v2/format-schema/resolver.mjs +1 -1
- package/dist/lib/v2/projection/creative-delivery.js +104 -29
- package/dist/lib/v2/projection/creative-delivery.mjs +108 -29
- package/dist/lib/v2/projection/index.d.mts +1 -0
- package/dist/lib/v2/projection/index.d.ts +1 -0
- package/dist/lib/v2/projection/index.js +3 -0
- package/dist/lib/v2/projection/index.mjs +2 -0
- package/dist/lib/v2/projection/legacy-metadata.d.mts +19 -0
- package/dist/lib/v2/projection/legacy-metadata.d.ts +19 -0
- package/dist/lib/v2/projection/legacy-metadata.js +91 -0
- package/dist/lib/v2/projection/legacy-metadata.mjs +86 -0
- package/dist/lib/v2/projection/v1-to-v2.d.mts +1 -1
- package/dist/lib/v2/projection/v1-to-v2.d.ts +1 -1
- package/dist/lib/v2/projection/v1-to-v2.js +12 -9
- package/dist/lib/v2/projection/v1-to-v2.mjs +12 -9
- package/dist/lib/validation/budget-allocation.d.mts +3 -3
- package/dist/lib/validation/budget-allocation.d.ts +3 -3
- package/dist/lib/validation/compact-schema.d.mts +27 -0
- package/dist/lib/validation/compact-schema.d.ts +27 -0
- package/dist/lib/validation/compact-schema.js +276 -0
- package/dist/lib/validation/compact-schema.mjs +250 -0
- package/dist/lib/validation/media-buy-delivery-report.d.mts +8 -0
- package/dist/lib/validation/media-buy-delivery-report.d.ts +8 -0
- package/dist/lib/validation/media-buy-delivery-report.js +31 -0
- package/dist/lib/validation/media-buy-delivery-report.mjs +7 -0
- package/dist/lib/validation/nonempty-array.d.mts +15 -0
- package/dist/lib/validation/nonempty-array.d.ts +15 -0
- package/dist/lib/validation/nonempty-array.js +41 -0
- package/dist/lib/validation/nonempty-array.mjs +7 -0
- package/dist/lib/validation/schema-diagnostic-origins.d.mts +21 -0
- package/dist/lib/validation/schema-diagnostic-origins.d.ts +21 -0
- package/dist/lib/validation/schema-diagnostic-origins.js +193 -0
- package/dist/lib/validation/schema-diagnostic-origins.mjs +169 -0
- package/dist/lib/validation/schema-loader.js +86 -16
- package/dist/lib/validation/schema-loader.mjs +82 -16
- package/dist/lib/validation/schema-validator.d.mts +10 -19
- package/dist/lib/validation/schema-validator.d.ts +10 -19
- package/dist/lib/validation/schema-validator.js +135 -42
- package/dist/lib/validation/schema-validator.mjs +139 -43
- package/dist/lib/validation/sync-creatives.d.mts +22 -22
- package/dist/lib/validation/sync-creatives.d.ts +22 -22
- 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.mjs +3 -3
- package/dist/lib/webhooks/index.d.mts +3 -0
- package/dist/lib/webhooks/index.d.ts +3 -0
- package/dist/lib/webhooks/index.js +3 -0
- package/dist/lib/webhooks/index.mjs +2 -0
- package/dist/lib/webhooks/media-buy-delivery.d.mts +43 -0
- package/dist/lib/webhooks/media-buy-delivery.d.ts +43 -0
- package/dist/lib/webhooks/media-buy-delivery.js +119 -0
- package/dist/lib/webhooks/media-buy-delivery.mjs +94 -0
- package/docs/TYPE-SUMMARY.md +2 -2
- package/docs/guides/DELIVERY-WEBHOOK-PARSING.md +142 -0
- package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +15 -0
- package/docs/guides/REPORTING-LEDGER.md +93 -0
- package/docs/guides/REPORTING-STABILITY.md +1 -1
- package/docs/guides/TYPED-CLIENT-TOOLS.md +49 -0
- package/docs/llms.txt +2 -2
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/docs/migration-16-to-17.md +191 -14
- package/docs/migration-6.6-to-6.7.md +14 -0
- package/docs/migration-account-change-feed.md +15 -0
- package/docs/recipes/verifying-inbound-webhooks.md +18 -2
- package/package.json +2 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { projectReportingDeliveryConfigStates } from "../reporting-delivery-config.mjs";
|
|
2
|
+
import { projectAccountResponseIdentityFields } from "../account-response-identity.mjs";
|
|
2
3
|
const ACCOUNT_AUTHORIZATION_WIRE_KEYS = [
|
|
3
4
|
"allowed_tasks",
|
|
4
5
|
"field_scopes",
|
|
@@ -19,6 +20,30 @@ class AccountNotFoundError extends Error {
|
|
|
19
20
|
super(message);
|
|
20
21
|
}
|
|
21
22
|
}
|
|
23
|
+
const SYNC_ACCOUNT_PASSTHROUGH_KEYS = [
|
|
24
|
+
"account_id",
|
|
25
|
+
"brand",
|
|
26
|
+
"operator",
|
|
27
|
+
"revision",
|
|
28
|
+
"currency",
|
|
29
|
+
"timezone",
|
|
30
|
+
"name",
|
|
31
|
+
"action",
|
|
32
|
+
"status",
|
|
33
|
+
"billing",
|
|
34
|
+
"account_scope",
|
|
35
|
+
"setup",
|
|
36
|
+
"rate_card",
|
|
37
|
+
"payment_terms",
|
|
38
|
+
"credit_limit",
|
|
39
|
+
"errors",
|
|
40
|
+
"warnings",
|
|
41
|
+
"sandbox"
|
|
42
|
+
];
|
|
43
|
+
const SYNC_ACCOUNTS_RESULT_KEY_COVERAGE = {};
|
|
44
|
+
void SYNC_ACCOUNTS_RESULT_KEY_COVERAGE;
|
|
45
|
+
const SYNC_ACCOUNTS_PROJECTION_KEY_COVERAGE = {};
|
|
46
|
+
void SYNC_ACCOUNTS_PROJECTION_KEY_COVERAGE;
|
|
22
47
|
function toWireAccount(account) {
|
|
23
48
|
const wire = {
|
|
24
49
|
account_id: account.id,
|
|
@@ -76,22 +101,19 @@ function projectAccountAuthorization(authorization) {
|
|
|
76
101
|
return projected;
|
|
77
102
|
}
|
|
78
103
|
function toWireSyncAccountRow(row) {
|
|
104
|
+
const identity = projectAccountResponseIdentityFields(row);
|
|
79
105
|
const wire = {
|
|
80
|
-
brand: row.brand,
|
|
81
|
-
operator: row.operator,
|
|
82
106
|
action: row.action,
|
|
83
|
-
|
|
107
|
+
...identity
|
|
84
108
|
};
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
109
|
+
const source = row;
|
|
110
|
+
function copyField(key) {
|
|
111
|
+
const value = source[key];
|
|
112
|
+
if (value !== void 0) wire[key] = value;
|
|
113
|
+
}
|
|
114
|
+
for (const key of SYNC_ACCOUNT_PASSTHROUGH_KEYS) copyField(key);
|
|
88
115
|
const projectedEntity = projectBillingEntity(row.billing_entity);
|
|
89
116
|
if (projectedEntity !== void 0) wire.billing_entity = projectedEntity;
|
|
90
|
-
if (row.account_scope !== void 0) wire.account_scope = row.account_scope;
|
|
91
|
-
if (row.setup !== void 0) wire.setup = row.setup;
|
|
92
|
-
if (row.rate_card !== void 0) wire.rate_card = row.rate_card;
|
|
93
|
-
if (row.payment_terms !== void 0) wire.payment_terms = row.payment_terms;
|
|
94
|
-
if (row.credit_limit !== void 0) wire.credit_limit = row.credit_limit;
|
|
95
117
|
if (row.notification_configs !== void 0) {
|
|
96
118
|
wire.notification_configs = row.notification_configs.map(projectNotificationConfig);
|
|
97
119
|
}
|
|
@@ -103,9 +125,6 @@ function toWireSyncAccountRow(row) {
|
|
|
103
125
|
row.authorization
|
|
104
126
|
);
|
|
105
127
|
}
|
|
106
|
-
if (row.errors !== void 0) wire.errors = row.errors;
|
|
107
|
-
if (row.warnings !== void 0) wire.warnings = row.warnings;
|
|
108
|
-
if (row.sandbox !== void 0) wire.sandbox = row.sandbox;
|
|
109
128
|
return wire;
|
|
110
129
|
}
|
|
111
130
|
function projectNotificationConfig(config) {
|
|
@@ -362,10 +362,10 @@ export interface CreateAdcpServerFromPlatformOptions<TAccount = unknown> extends
|
|
|
362
362
|
ctxMetadata?: CtxMetadataStore;
|
|
363
363
|
/**
|
|
364
364
|
* Opinionated media-buy store that satisfies the seller spec contract for
|
|
365
|
-
*
|
|
366
|
-
* `
|
|
367
|
-
* `
|
|
368
|
-
* `collection_list` references.
|
|
365
|
+
* creation context and targeting echo: persist buy/package `context` and
|
|
366
|
+
* `packages[].targeting_overlay` from `create_media_buy`, then fill missing
|
|
367
|
+
* fields on `get_media_buys`. Targeting updates preserve creation context
|
|
368
|
+
* and prior `property_list` / `collection_list` references.
|
|
369
369
|
*
|
|
370
370
|
* Wire to honor the
|
|
371
371
|
* `schemas/cache/<v>/media-buy/get-media-buys-response.json` contract
|
|
@@ -373,7 +373,7 @@ export interface CreateAdcpServerFromPlatformOptions<TAccount = unknown> extends
|
|
|
373
373
|
* `property-lists` / `collection-lists` MUST echo the persisted refs;
|
|
374
374
|
* `mediaBuyStore` is the framework-side way to do it.
|
|
375
375
|
*
|
|
376
|
-
* Backed by any `AdcpStateStore
|
|
376
|
+
* Backed by any `AdcpStateStore`: `InMemoryStateStore` for dev,
|
|
377
377
|
* `PostgresStateStore` for production. Failures are logged and swallowed
|
|
378
378
|
* (auto-echo MUST NOT break a successful seller response).
|
|
379
379
|
*
|
|
@@ -362,10 +362,10 @@ export interface CreateAdcpServerFromPlatformOptions<TAccount = unknown> extends
|
|
|
362
362
|
ctxMetadata?: CtxMetadataStore;
|
|
363
363
|
/**
|
|
364
364
|
* Opinionated media-buy store that satisfies the seller spec contract for
|
|
365
|
-
*
|
|
366
|
-
* `
|
|
367
|
-
* `
|
|
368
|
-
* `collection_list` references.
|
|
365
|
+
* creation context and targeting echo: persist buy/package `context` and
|
|
366
|
+
* `packages[].targeting_overlay` from `create_media_buy`, then fill missing
|
|
367
|
+
* fields on `get_media_buys`. Targeting updates preserve creation context
|
|
368
|
+
* and prior `property_list` / `collection_list` references.
|
|
369
369
|
*
|
|
370
370
|
* Wire to honor the
|
|
371
371
|
* `schemas/cache/<v>/media-buy/get-media-buys-response.json` contract
|
|
@@ -373,7 +373,7 @@ export interface CreateAdcpServerFromPlatformOptions<TAccount = unknown> extends
|
|
|
373
373
|
* `property-lists` / `collection-lists` MUST echo the persisted refs;
|
|
374
374
|
* `mediaBuyStore` is the framework-side way to do it.
|
|
375
375
|
*
|
|
376
|
-
* Backed by any `AdcpStateStore
|
|
376
|
+
* Backed by any `AdcpStateStore`: `InMemoryStateStore` for dev,
|
|
377
377
|
* `PostgresStateStore` for production. Failures are logged and swallowed
|
|
378
378
|
* (auto-echo MUST NOT break a successful seller response).
|
|
379
379
|
*
|
|
@@ -3270,7 +3270,7 @@ async function autoStoreResources(store, accountId, kind, resources, idField, lo
|
|
|
3270
3270
|
);
|
|
3271
3271
|
}
|
|
3272
3272
|
}
|
|
3273
|
-
async function
|
|
3273
|
+
async function persistMediaBuyFromCreate(store, accountId, request, result, logger) {
|
|
3274
3274
|
if (!store || !accountId) return;
|
|
3275
3275
|
if (result == null || typeof result !== "object") return;
|
|
3276
3276
|
try {
|
|
@@ -3293,7 +3293,7 @@ async function persistTargetingOverlayFromUpdate(store, accountId, mediaBuyId, p
|
|
|
3293
3293
|
logger.warn(`[adcp/decisioning] mediaBuyStore.mergeFromUpdate failed: ${msg}`);
|
|
3294
3294
|
}
|
|
3295
3295
|
}
|
|
3296
|
-
async function
|
|
3296
|
+
async function backfillMediaBuyState(store, accountId, result, logger) {
|
|
3297
3297
|
if (!store || !accountId) return;
|
|
3298
3298
|
if (result == null || typeof result !== "object") return;
|
|
3299
3299
|
try {
|
|
@@ -4081,7 +4081,7 @@ function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observab
|
|
|
4081
4081
|
},
|
|
4082
4082
|
result,
|
|
4083
4083
|
async (r) => {
|
|
4084
|
-
await
|
|
4084
|
+
await persistMediaBuyFromCreate(mediaBuyStore, reqCtx.account?.id, params, r, logger);
|
|
4085
4085
|
return asSemanticServerResponseForWire(
|
|
4086
4086
|
r,
|
|
4087
4087
|
"create_media_buy",
|
|
@@ -4369,7 +4369,7 @@ function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observab
|
|
|
4369
4369
|
canonicalFormatLegacyResolver,
|
|
4370
4370
|
responseWireMode
|
|
4371
4371
|
);
|
|
4372
|
-
await
|
|
4372
|
+
await backfillMediaBuyState(mediaBuyStore, reqCtx.account?.id, wireResult, logger);
|
|
4373
4373
|
return wireResult;
|
|
4374
4374
|
},
|
|
4375
4375
|
(r) => r
|
|
@@ -3302,7 +3302,7 @@ async function autoStoreResources(store, accountId, kind, resources, idField, lo
|
|
|
3302
3302
|
);
|
|
3303
3303
|
}
|
|
3304
3304
|
}
|
|
3305
|
-
async function
|
|
3305
|
+
async function persistMediaBuyFromCreate(store, accountId, request, result, logger) {
|
|
3306
3306
|
if (!store || !accountId) return;
|
|
3307
3307
|
if (result == null || typeof result !== "object") return;
|
|
3308
3308
|
try {
|
|
@@ -3325,7 +3325,7 @@ async function persistTargetingOverlayFromUpdate(store, accountId, mediaBuyId, p
|
|
|
3325
3325
|
logger.warn(`[adcp/decisioning] mediaBuyStore.mergeFromUpdate failed: ${msg}`);
|
|
3326
3326
|
}
|
|
3327
3327
|
}
|
|
3328
|
-
async function
|
|
3328
|
+
async function backfillMediaBuyState(store, accountId, result, logger) {
|
|
3329
3329
|
if (!store || !accountId) return;
|
|
3330
3330
|
if (result == null || typeof result !== "object") return;
|
|
3331
3331
|
try {
|
|
@@ -4113,7 +4113,7 @@ function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observab
|
|
|
4113
4113
|
},
|
|
4114
4114
|
result,
|
|
4115
4115
|
async (r) => {
|
|
4116
|
-
await
|
|
4116
|
+
await persistMediaBuyFromCreate(mediaBuyStore, reqCtx.account?.id, params, r, logger);
|
|
4117
4117
|
return asSemanticServerResponseForWire(
|
|
4118
4118
|
r,
|
|
4119
4119
|
"create_media_buy",
|
|
@@ -4401,7 +4401,7 @@ function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observab
|
|
|
4401
4401
|
canonicalFormatLegacyResolver,
|
|
4402
4402
|
responseWireMode
|
|
4403
4403
|
);
|
|
4404
|
-
await
|
|
4404
|
+
await backfillMediaBuyState(mediaBuyStore, reqCtx.account?.id, wireResult, logger);
|
|
4405
4405
|
return wireResult;
|
|
4406
4406
|
},
|
|
4407
4407
|
(r) => r
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Opinionated media-buy store that satisfies the seller's spec contract:
|
|
3
|
-
* persist `packages[].targeting_overlay` from
|
|
4
|
-
* `get_media_buys`, and
|
|
3
|
+
* persist creation context and `packages[].targeting_overlay` from
|
|
4
|
+
* `create_media_buy`, echo them on `get_media_buys`, and merge targeting
|
|
5
|
+
* updates without dropping creation context or prior
|
|
5
6
|
* `property_list` / `collection_list` references.
|
|
6
7
|
*
|
|
7
8
|
* Per `schemas/cache/<v>/media-buy/get-media-buys-response.json` the seller
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
* by hand.
|
|
13
14
|
*
|
|
14
15
|
* Adopters opt in by passing `mediaBuyStore` to
|
|
15
|
-
* `createAdcpServerFromPlatform`. Backed by any `AdcpStateStore
|
|
16
|
+
* `createAdcpServerFromPlatform`. Backed by any `AdcpStateStore`:
|
|
16
17
|
* `InMemoryStateStore` for development, `PostgresStateStore` for
|
|
17
18
|
* production.
|
|
18
19
|
*
|
|
@@ -41,9 +42,13 @@ export declare const DEFAULT_MEDIA_BUY_STORE_COLLECTION = "media_buys_targeting"
|
|
|
41
42
|
* request to the full generated type just to thread it through.
|
|
42
43
|
*/
|
|
43
44
|
export interface CreateMediaBuyInputForStore {
|
|
45
|
+
/** Opaque creation context, persisted verbatim for resource readback. */
|
|
46
|
+
context?: Record<string, unknown>;
|
|
44
47
|
packages?: Array<{
|
|
45
48
|
package_id?: string;
|
|
46
49
|
buyer_ref?: string;
|
|
50
|
+
product_id?: string;
|
|
51
|
+
context?: Record<string, unknown>;
|
|
47
52
|
/**
|
|
48
53
|
* Request-shaped Targeting Input: individual dimensions may be `null` to
|
|
49
54
|
* suppress a configured-product or product default (AdCP 3.2, DR-0020).
|
|
@@ -58,9 +63,12 @@ export interface CreateMediaBuyInputForStore {
|
|
|
58
63
|
*/
|
|
59
64
|
export interface CreateMediaBuyResultForStore {
|
|
60
65
|
media_buy_id: string;
|
|
66
|
+
context?: Record<string, unknown>;
|
|
61
67
|
packages?: Array<{
|
|
62
68
|
package_id?: string;
|
|
63
69
|
buyer_ref?: string;
|
|
70
|
+
product_id?: string;
|
|
71
|
+
context?: Record<string, unknown>;
|
|
64
72
|
targeting_overlay?: TargetingOverlay;
|
|
65
73
|
}>;
|
|
66
74
|
}
|
|
@@ -89,18 +97,23 @@ export interface UpdateMediaBuyInputForStore {
|
|
|
89
97
|
export interface GetMediaBuysResultForStore {
|
|
90
98
|
media_buys?: Array<{
|
|
91
99
|
media_buy_id?: string;
|
|
100
|
+
context?: Record<string, unknown>;
|
|
92
101
|
packages?: Array<{
|
|
93
102
|
package_id?: string;
|
|
103
|
+
context?: Record<string, unknown>;
|
|
94
104
|
targeting_overlay?: TargetingOverlay;
|
|
95
105
|
}>;
|
|
96
106
|
}>;
|
|
97
107
|
}
|
|
98
108
|
export interface MediaBuyStore {
|
|
99
109
|
/**
|
|
100
|
-
* Persist `packages[].targeting_overlay`
|
|
101
|
-
* `create_media_buy`. Joins the request's per-package targeting
|
|
110
|
+
* Persist buy/package creation context and `packages[].targeting_overlay`
|
|
111
|
+
* from a successful `create_media_buy`. Joins the request's per-package targeting
|
|
102
112
|
* overlay with the response's seller-assigned `package_id` (or
|
|
103
|
-
* `buyer_ref` when the request used buyer-supplied refs).
|
|
113
|
+
* `buyer_ref` when the request used buyer-supplied refs). Context uses
|
|
114
|
+
* unambiguous package identities, then positional alignment only when
|
|
115
|
+
* package counts agree and echoed identities do not contradict it.
|
|
116
|
+
* Existing creation context is retained on repeated persistence calls.
|
|
104
117
|
*/
|
|
105
118
|
persistFromCreate(accountId: string, request: CreateMediaBuyInputForStore, result: CreateMediaBuyResultForStore): Promise<void>;
|
|
106
119
|
/**
|
|
@@ -112,21 +125,22 @@ export interface MediaBuyStore {
|
|
|
112
125
|
* - field present and `null` → clear (drop the field)
|
|
113
126
|
*
|
|
114
127
|
* A patch that clears the last surviving dimension drops the package's
|
|
115
|
-
* tracked overlay entirely, so `backfill` stops echoing one
|
|
128
|
+
* tracked overlay entirely, so `backfill` stops echoing one. A cleared
|
|
116
129
|
* dimension is absent from effective readback rather than present as `null`.
|
|
117
130
|
*
|
|
118
131
|
* `new_packages` from the patch are persisted as fresh entries when
|
|
119
132
|
* they declare `targeting_overlay`. Entries that omit it are
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* one becomes relevant.
|
|
133
|
+
* not tracked. Updates preserve creation context and do not capture
|
|
134
|
+
* context for packages added after creation.
|
|
123
135
|
*/
|
|
124
136
|
mergeFromUpdate(accountId: string, mediaBuyId: string, patch: UpdateMediaBuyInputForStore): Promise<void>;
|
|
125
137
|
/**
|
|
126
|
-
* Fill in missing
|
|
138
|
+
* Fill in missing buy/package creation context and
|
|
139
|
+
* `packages[].targeting_overlay` on the seller's
|
|
127
140
|
* `get_media_buys` response from the persisted store. **Mutates the
|
|
128
141
|
* response in place** (and returns it for fluent chaining). Packages
|
|
129
|
-
* the seller already echoed are left untouched.
|
|
142
|
+
* the seller already echoed are left untouched. The top-level response
|
|
143
|
+
* context belongs to the read request and is never changed.
|
|
130
144
|
*/
|
|
131
145
|
backfill<T extends GetMediaBuysResultForStore>(accountId: string, result: T): Promise<T>;
|
|
132
146
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Opinionated media-buy store that satisfies the seller's spec contract:
|
|
3
|
-
* persist `packages[].targeting_overlay` from
|
|
4
|
-
* `get_media_buys`, and
|
|
3
|
+
* persist creation context and `packages[].targeting_overlay` from
|
|
4
|
+
* `create_media_buy`, echo them on `get_media_buys`, and merge targeting
|
|
5
|
+
* updates without dropping creation context or prior
|
|
5
6
|
* `property_list` / `collection_list` references.
|
|
6
7
|
*
|
|
7
8
|
* Per `schemas/cache/<v>/media-buy/get-media-buys-response.json` the seller
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
* by hand.
|
|
13
14
|
*
|
|
14
15
|
* Adopters opt in by passing `mediaBuyStore` to
|
|
15
|
-
* `createAdcpServerFromPlatform`. Backed by any `AdcpStateStore
|
|
16
|
+
* `createAdcpServerFromPlatform`. Backed by any `AdcpStateStore`:
|
|
16
17
|
* `InMemoryStateStore` for development, `PostgresStateStore` for
|
|
17
18
|
* production.
|
|
18
19
|
*
|
|
@@ -41,9 +42,13 @@ export declare const DEFAULT_MEDIA_BUY_STORE_COLLECTION = "media_buys_targeting"
|
|
|
41
42
|
* request to the full generated type just to thread it through.
|
|
42
43
|
*/
|
|
43
44
|
export interface CreateMediaBuyInputForStore {
|
|
45
|
+
/** Opaque creation context, persisted verbatim for resource readback. */
|
|
46
|
+
context?: Record<string, unknown>;
|
|
44
47
|
packages?: Array<{
|
|
45
48
|
package_id?: string;
|
|
46
49
|
buyer_ref?: string;
|
|
50
|
+
product_id?: string;
|
|
51
|
+
context?: Record<string, unknown>;
|
|
47
52
|
/**
|
|
48
53
|
* Request-shaped Targeting Input: individual dimensions may be `null` to
|
|
49
54
|
* suppress a configured-product or product default (AdCP 3.2, DR-0020).
|
|
@@ -58,9 +63,12 @@ export interface CreateMediaBuyInputForStore {
|
|
|
58
63
|
*/
|
|
59
64
|
export interface CreateMediaBuyResultForStore {
|
|
60
65
|
media_buy_id: string;
|
|
66
|
+
context?: Record<string, unknown>;
|
|
61
67
|
packages?: Array<{
|
|
62
68
|
package_id?: string;
|
|
63
69
|
buyer_ref?: string;
|
|
70
|
+
product_id?: string;
|
|
71
|
+
context?: Record<string, unknown>;
|
|
64
72
|
targeting_overlay?: TargetingOverlay;
|
|
65
73
|
}>;
|
|
66
74
|
}
|
|
@@ -89,18 +97,23 @@ export interface UpdateMediaBuyInputForStore {
|
|
|
89
97
|
export interface GetMediaBuysResultForStore {
|
|
90
98
|
media_buys?: Array<{
|
|
91
99
|
media_buy_id?: string;
|
|
100
|
+
context?: Record<string, unknown>;
|
|
92
101
|
packages?: Array<{
|
|
93
102
|
package_id?: string;
|
|
103
|
+
context?: Record<string, unknown>;
|
|
94
104
|
targeting_overlay?: TargetingOverlay;
|
|
95
105
|
}>;
|
|
96
106
|
}>;
|
|
97
107
|
}
|
|
98
108
|
export interface MediaBuyStore {
|
|
99
109
|
/**
|
|
100
|
-
* Persist `packages[].targeting_overlay`
|
|
101
|
-
* `create_media_buy`. Joins the request's per-package targeting
|
|
110
|
+
* Persist buy/package creation context and `packages[].targeting_overlay`
|
|
111
|
+
* from a successful `create_media_buy`. Joins the request's per-package targeting
|
|
102
112
|
* overlay with the response's seller-assigned `package_id` (or
|
|
103
|
-
* `buyer_ref` when the request used buyer-supplied refs).
|
|
113
|
+
* `buyer_ref` when the request used buyer-supplied refs). Context uses
|
|
114
|
+
* unambiguous package identities, then positional alignment only when
|
|
115
|
+
* package counts agree and echoed identities do not contradict it.
|
|
116
|
+
* Existing creation context is retained on repeated persistence calls.
|
|
104
117
|
*/
|
|
105
118
|
persistFromCreate(accountId: string, request: CreateMediaBuyInputForStore, result: CreateMediaBuyResultForStore): Promise<void>;
|
|
106
119
|
/**
|
|
@@ -112,21 +125,22 @@ export interface MediaBuyStore {
|
|
|
112
125
|
* - field present and `null` → clear (drop the field)
|
|
113
126
|
*
|
|
114
127
|
* A patch that clears the last surviving dimension drops the package's
|
|
115
|
-
* tracked overlay entirely, so `backfill` stops echoing one
|
|
128
|
+
* tracked overlay entirely, so `backfill` stops echoing one. A cleared
|
|
116
129
|
* dimension is absent from effective readback rather than present as `null`.
|
|
117
130
|
*
|
|
118
131
|
* `new_packages` from the patch are persisted as fresh entries when
|
|
119
132
|
* they declare `targeting_overlay`. Entries that omit it are
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* one becomes relevant.
|
|
133
|
+
* not tracked. Updates preserve creation context and do not capture
|
|
134
|
+
* context for packages added after creation.
|
|
123
135
|
*/
|
|
124
136
|
mergeFromUpdate(accountId: string, mediaBuyId: string, patch: UpdateMediaBuyInputForStore): Promise<void>;
|
|
125
137
|
/**
|
|
126
|
-
* Fill in missing
|
|
138
|
+
* Fill in missing buy/package creation context and
|
|
139
|
+
* `packages[].targeting_overlay` on the seller's
|
|
127
140
|
* `get_media_buys` response from the persisted store. **Mutates the
|
|
128
141
|
* response in place** (and returns it for fluent chaining). Packages
|
|
129
|
-
* the seller already echoed are left untouched.
|
|
142
|
+
* the seller already echoed are left untouched. The top-level response
|
|
143
|
+
* context belongs to the read request and is never changed.
|
|
130
144
|
*/
|
|
131
145
|
backfill<T extends GetMediaBuysResultForStore>(accountId: string, result: T): Promise<T>;
|
|
132
146
|
}
|
|
@@ -25,6 +25,25 @@ module.exports = __toCommonJS(media_buy_store_exports);
|
|
|
25
25
|
var import_targeting_input = require('../media-buy/targeting-input.js');
|
|
26
26
|
var import_state_store = require('./state-store.js');
|
|
27
27
|
const DEFAULT_MEDIA_BUY_STORE_COLLECTION = "media_buys_targeting";
|
|
28
|
+
const PACKAGE_IDENTITY_FIELDS = ["package_id", "product_id", "buyer_ref"];
|
|
29
|
+
function compatibleIdentity(left, right) {
|
|
30
|
+
if (!left || !right) return false;
|
|
31
|
+
return PACKAGE_IDENTITY_FIELDS.every((key) => !left[key] || !right[key] || left[key] === right[key]);
|
|
32
|
+
}
|
|
33
|
+
function sharesIdentity(left, right) {
|
|
34
|
+
if (!left || !right) return false;
|
|
35
|
+
return compatibleIdentity(left, right) && PACKAGE_IDENTITY_FIELDS.some((key) => left[key] && left[key] === right[key]);
|
|
36
|
+
}
|
|
37
|
+
function matchContextPackage(requests, responses, index) {
|
|
38
|
+
const matches = requests.filter((request) => sharesIdentity(request, responses[index]));
|
|
39
|
+
if (matches.length === 1 && responses.filter((response) => sharesIdentity(matches[0], response)).length === 1) {
|
|
40
|
+
return matches[0];
|
|
41
|
+
}
|
|
42
|
+
if (requests.length === responses.length && requests.every((request, i) => compatibleIdentity(request, responses[i]))) {
|
|
43
|
+
return requests[index];
|
|
44
|
+
}
|
|
45
|
+
return void 0;
|
|
46
|
+
}
|
|
28
47
|
function createMediaBuyStore(options) {
|
|
29
48
|
const collection = options.collection ?? DEFAULT_MEDIA_BUY_STORE_COLLECTION;
|
|
30
49
|
function viewFor(accountId) {
|
|
@@ -42,8 +61,9 @@ function createMediaBuyStore(options) {
|
|
|
42
61
|
async persistFromCreate(accountId, request, result) {
|
|
43
62
|
const requestPackages = request.packages ?? [];
|
|
44
63
|
const responsePackages = result.packages ?? [];
|
|
45
|
-
if (
|
|
46
|
-
const
|
|
64
|
+
if (!result.media_buy_id) return;
|
|
65
|
+
const prior = await loadRecord(accountId, result.media_buy_id);
|
|
66
|
+
const byId = new Map((prior?.packages ?? []).map((pkg) => [pkg.package_id, { ...pkg }]));
|
|
47
67
|
for (let i = 0; i < requestPackages.length; i++) {
|
|
48
68
|
const reqPkg = requestPackages[i];
|
|
49
69
|
if (!reqPkg?.targeting_overlay) continue;
|
|
@@ -54,12 +74,26 @@ function createMediaBuyStore(options) {
|
|
|
54
74
|
if (!packageId) continue;
|
|
55
75
|
const persistedOverlay = respPkg?.targeting_overlay ?? (0, import_targeting_input.resolveTargetingInput)(reqPkg.targeting_overlay);
|
|
56
76
|
if (!persistedOverlay) continue;
|
|
57
|
-
|
|
77
|
+
byId.set(packageId, { ...byId.get(packageId), package_id: packageId, targeting_overlay: persistedOverlay });
|
|
58
78
|
}
|
|
59
|
-
|
|
79
|
+
for (const [index, response] of responsePackages.entries()) {
|
|
80
|
+
if (!response.package_id) continue;
|
|
81
|
+
const context2 = matchContextPackage(requestPackages, responsePackages, index)?.context ?? response.context;
|
|
82
|
+
const stored = byId.get(response.package_id);
|
|
83
|
+
if (context2 !== void 0 && stored?.context === void 0) {
|
|
84
|
+
byId.set(response.package_id, {
|
|
85
|
+
...stored,
|
|
86
|
+
package_id: response.package_id,
|
|
87
|
+
context: structuredClone(context2)
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const context = prior?.context ?? request.context ?? result.context;
|
|
92
|
+
if (byId.size === 0 && context === void 0) return;
|
|
60
93
|
await writeRecord(accountId, {
|
|
61
94
|
media_buy_id: result.media_buy_id,
|
|
62
|
-
|
|
95
|
+
...context !== void 0 ? { context: structuredClone(context) } : {},
|
|
96
|
+
packages: Array.from(byId.values())
|
|
63
97
|
});
|
|
64
98
|
},
|
|
65
99
|
async mergeFromUpdate(accountId, mediaBuyId, patch) {
|
|
@@ -67,42 +101,56 @@ function createMediaBuyStore(options) {
|
|
|
67
101
|
media_buy_id: mediaBuyId,
|
|
68
102
|
packages: []
|
|
69
103
|
};
|
|
70
|
-
const byId = new Map(prior.packages.map((p) => [p.package_id, p
|
|
104
|
+
const byId = new Map(prior.packages.map((p) => [p.package_id, { ...p }]));
|
|
71
105
|
for (const pkg of patch.packages ?? []) {
|
|
72
106
|
const packageId = pkg?.package_id;
|
|
73
107
|
if (!packageId) continue;
|
|
74
108
|
if (!("targeting_overlay" in pkg)) continue;
|
|
75
109
|
const incoming = pkg.targeting_overlay;
|
|
76
110
|
if (incoming === void 0) continue;
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
111
|
+
const stored = byId.get(packageId);
|
|
112
|
+
const merged = (0, import_targeting_input.applyTargetingInput)(stored?.targeting_overlay, incoming);
|
|
113
|
+
if (merged) byId.set(packageId, { ...stored, package_id: packageId, targeting_overlay: merged });
|
|
114
|
+
else if (stored?.context !== void 0) {
|
|
115
|
+
byId.set(packageId, { package_id: packageId, context: stored.context });
|
|
116
|
+
} else byId.delete(packageId);
|
|
80
117
|
}
|
|
81
118
|
for (const pkg of patch.new_packages ?? []) {
|
|
82
119
|
if (!pkg?.targeting_overlay || !pkg.package_id) continue;
|
|
83
120
|
const resolved = (0, import_targeting_input.resolveTargetingInput)(pkg.targeting_overlay);
|
|
84
|
-
if (resolved)
|
|
121
|
+
if (resolved)
|
|
122
|
+
byId.set(pkg.package_id, {
|
|
123
|
+
...byId.get(pkg.package_id),
|
|
124
|
+
package_id: pkg.package_id,
|
|
125
|
+
targeting_overlay: resolved
|
|
126
|
+
});
|
|
85
127
|
}
|
|
86
128
|
await writeRecord(accountId, {
|
|
87
|
-
|
|
88
|
-
packages: Array.from(byId.
|
|
89
|
-
package_id,
|
|
90
|
-
targeting_overlay
|
|
91
|
-
}))
|
|
129
|
+
...prior,
|
|
130
|
+
packages: Array.from(byId.values())
|
|
92
131
|
});
|
|
93
132
|
},
|
|
94
133
|
async backfill(accountId, result) {
|
|
95
134
|
const buys = result.media_buys;
|
|
96
135
|
if (!buys || buys.length === 0) return result;
|
|
97
136
|
for (const buy of buys) {
|
|
98
|
-
if (!buy?.media_buy_id
|
|
137
|
+
if (!buy?.media_buy_id) continue;
|
|
99
138
|
const record = await loadRecord(accountId, buy.media_buy_id);
|
|
100
139
|
if (!record) continue;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
140
|
+
if (buy.context === void 0 && record.context !== void 0) {
|
|
141
|
+
buy.context = structuredClone(record.context);
|
|
142
|
+
}
|
|
143
|
+
const byId = new Map(record.packages.map((p) => [p.package_id, p]));
|
|
144
|
+
for (const pkg of buy.packages ?? []) {
|
|
145
|
+
if (!pkg?.package_id) continue;
|
|
146
|
+
const persisted = byId.get(pkg.package_id);
|
|
147
|
+
if (!persisted) continue;
|
|
148
|
+
if (pkg.targeting_overlay === void 0 && persisted.targeting_overlay !== void 0) {
|
|
149
|
+
pkg.targeting_overlay = persisted.targeting_overlay;
|
|
150
|
+
}
|
|
151
|
+
if (pkg.context === void 0 && persisted.context !== void 0) {
|
|
152
|
+
pkg.context = structuredClone(persisted.context);
|
|
153
|
+
}
|
|
106
154
|
}
|
|
107
155
|
}
|
|
108
156
|
return result;
|