@adcp/sdk 15.9.4 → 15.9.6
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/core/AgentClient.d.mts +4 -2
- package/dist/lib/core/AgentClient.d.ts +4 -2
- package/dist/lib/core/AgentClient.js +4 -2
- package/dist/lib/core/AgentClient.mjs +4 -2
- package/dist/lib/core/SingleAgentClient.d.mts +7 -3
- package/dist/lib/core/SingleAgentClient.d.ts +7 -3
- package/dist/lib/core/SingleAgentClient.js +204 -13
- package/dist/lib/core/SingleAgentClient.mjs +209 -13
- package/dist/lib/core/TaskExecutor.d.mts +1 -0
- package/dist/lib/core/TaskExecutor.d.ts +1 -0
- package/dist/lib/core/TaskExecutor.js +48 -34
- package/dist/lib/core/TaskExecutor.mjs +49 -35
- package/dist/lib/core/product-cache.d.mts +3 -1
- package/dist/lib/core/product-cache.d.ts +3 -1
- package/dist/lib/core/product-cache.js +2 -1
- package/dist/lib/core/product-cache.mjs +2 -1
- package/dist/lib/registry/types.d.mts +3 -2
- package/dist/lib/registry/types.d.ts +3 -2
- package/dist/lib/registry/types.generated.d.mts +21 -9
- package/dist/lib/registry/types.generated.d.ts +21 -9
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +6 -2
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +6 -2
- package/dist/lib/testing/client.js +3 -5
- package/dist/lib/testing/client.mjs +4 -6
- package/dist/lib/testing/compliance/comply.js +7 -2
- package/dist/lib/testing/compliance/comply.mjs +8 -3
- package/dist/lib/testing/index.d.mts +1 -1
- package/dist/lib/testing/index.d.ts +1 -1
- package/dist/lib/testing/index.js +4 -2
- package/dist/lib/testing/index.mjs +8 -2
- package/dist/lib/testing/storyboard/runner.js +12 -12
- package/dist/lib/testing/storyboard/runner.mjs +14 -13
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/testing/storyboard/validations.js +23 -1
- package/dist/lib/testing/storyboard/validations.mjs +28 -2
- package/dist/lib/testing/types.d.mts +39 -0
- package/dist/lib/testing/types.d.ts +39 -0
- package/dist/lib/v2/projection/augment-response.js +6 -3
- package/dist/lib/v2/projection/augment-response.mjs +8 -5
- package/dist/lib/v2/projection/creative-delivery.d.mts +2 -0
- package/dist/lib/v2/projection/creative-delivery.d.ts +2 -0
- package/dist/lib/v2/projection/creative-delivery.js +36 -17
- package/dist/lib/v2/projection/creative-delivery.mjs +37 -18
- package/dist/lib/v2/projection/legacy-metadata.d.mts +12 -0
- package/dist/lib/v2/projection/legacy-metadata.d.ts +12 -0
- package/dist/lib/v2/projection/legacy-metadata.js +41 -1
- package/dist/lib/v2/projection/legacy-metadata.mjs +37 -1
- package/dist/lib/v2/projection/v1-to-v2.d.mts +7 -0
- package/dist/lib/v2/projection/v1-to-v2.d.ts +7 -0
- package/dist/lib/v2/projection/v1-to-v2.js +83 -2
- package/dist/lib/v2/projection/v1-to-v2.mjs +86 -1
- package/dist/lib/validation/index.d.mts +1 -1
- package/dist/lib/validation/index.d.ts +1 -1
- package/dist/lib/validation/index.js +4 -2
- package/dist/lib/validation/index.mjs +4 -2
- package/dist/lib/validation/schema-loader.d.mts +26 -0
- package/dist/lib/validation/schema-loader.d.ts +26 -0
- package/dist/lib/validation/schema-loader.js +98 -14
- package/dist/lib/validation/schema-loader.mjs +95 -13
- 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/docs/TYPE-SUMMARY.md +2 -2
- package/docs/guides/CREATIVE-DELIVERY.md +45 -6
- package/docs/guides/VALIDATE-YOUR-AGENT.md +34 -0
- package/docs/llms.txt +2 -2
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/package.json +1 -1
|
@@ -159,6 +159,7 @@ import { resolvePropertyList } from "../server/targeting-helpers.mjs";
|
|
|
159
159
|
import {
|
|
160
160
|
CreativeFormatCapabilityError,
|
|
161
161
|
CreativeFormatProjectionError,
|
|
162
|
+
canUseProductOptionsForCreativeWire,
|
|
162
163
|
projectMediaBuyCreativesForDelivery,
|
|
163
164
|
projectCreativeForDelivery,
|
|
164
165
|
projectSyncCreativesForDelivery,
|
|
@@ -176,6 +177,10 @@ import {
|
|
|
176
177
|
import { toCanonicalOnlyResponse } from "../v2/projection/augment-response.mjs";
|
|
177
178
|
import {
|
|
178
179
|
legacyFormatRefsForDeclaration,
|
|
180
|
+
isSynthesizedFormatOption,
|
|
181
|
+
selectedFormatOptions,
|
|
182
|
+
rememberSellerFormatEvidence,
|
|
183
|
+
sellerFormatEvidence,
|
|
179
184
|
rememberSellerDeclaredFormatOption,
|
|
180
185
|
sellerDeclaredFormatOption,
|
|
181
186
|
structuredCloneWithLegacyCreativeMetadata
|
|
@@ -299,6 +304,56 @@ const RECORDLESS_HMAC_READ_ONLY_TASKS = /* @__PURE__ */ new Set([
|
|
|
299
304
|
]);
|
|
300
305
|
const TASK_SCOPED_STATE_LIMIT = 1e4;
|
|
301
306
|
const WEBHOOK_JWKS_RESOLVER_LIMIT = 1024;
|
|
307
|
+
function creativeMatchesProductOption(creative, declaration) {
|
|
308
|
+
const params = isPlainRecord(declaration.params) ? declaration.params : {};
|
|
309
|
+
const assets = isPlainRecord(creative.assets) ? creative.assets : {};
|
|
310
|
+
const slots = Array.isArray(params.slots) ? params.slots : [];
|
|
311
|
+
if (!slots.every((slot) => {
|
|
312
|
+
if (!isPlainRecord(slot) || typeof slot.asset_group_id !== "string") return false;
|
|
313
|
+
const value = assets[slot.asset_group_id];
|
|
314
|
+
const entries = value === void 0 ? [] : Array.isArray(value) ? value : [value];
|
|
315
|
+
const minimum = Math.max(typeof slot.min === "number" ? slot.min : 0, slot.required === true ? 1 : 0);
|
|
316
|
+
if (entries.length < minimum || typeof slot.max === "number" && entries.length > slot.max) return false;
|
|
317
|
+
return entries.every(
|
|
318
|
+
(asset) => isPlainRecord(asset) && (typeof slot.asset_type !== "string" || asset.asset_type === slot.asset_type)
|
|
319
|
+
);
|
|
320
|
+
}))
|
|
321
|
+
return false;
|
|
322
|
+
const formatParams = isPlainRecord(creative.format_parameters) ? creative.format_parameters : {};
|
|
323
|
+
const kind = String(creative.format_kind);
|
|
324
|
+
const mediaType = kind.startsWith("image") ? "image" : kind.startsWith("video") ? "video" : kind.startsWith("audio") ? "audio" : kind === "html5" ? "html" : void 0;
|
|
325
|
+
const assetTypes = mediaType === "video" ? ["video", "vast"] : mediaType === "audio" ? ["audio", "vast", "daast"] : mediaType === "html" ? ["html", "zip"] : mediaType ? [mediaType] : ["image", "video", "audio", "html", "zip", "vast", "daast"];
|
|
326
|
+
const requiredMediaSlots = slots.filter(
|
|
327
|
+
(slot) => isPlainRecord(slot) && (slot.required === true || typeof slot.min === "number" && slot.min > 0) && assetTypes.includes(String(slot.asset_type))
|
|
328
|
+
);
|
|
329
|
+
const preferredGroups = mediaType ? [`${mediaType}_main`, mediaType, kind, ...assetTypes] : [];
|
|
330
|
+
const primaryGroup = (requiredMediaSlots.length === 1 ? String(requiredMediaSlots[0].asset_group_id) : void 0) ?? preferredGroups.find((group) => assets[group] !== void 0);
|
|
331
|
+
const sourceAssets = primaryGroup ? [assets[primaryGroup]] : Object.values(assets);
|
|
332
|
+
const dimensionalAssets = sourceAssets.flatMap((value) => Array.isArray(value) ? value : [value]).filter(
|
|
333
|
+
(value) => isPlainRecord(value) && assetTypes.includes(String(value.asset_type))
|
|
334
|
+
);
|
|
335
|
+
return (dimensionalAssets.length > 0 ? dimensionalAssets : [{}]).every((asset) => {
|
|
336
|
+
const actual = { ...asset, ...formatParams };
|
|
337
|
+
for (const key of ["width", "height"]) {
|
|
338
|
+
if (typeof params[key] === "number" && actual[key] !== params[key]) return false;
|
|
339
|
+
const min = params[`min_${key}`];
|
|
340
|
+
const max = params[`max_${key}`];
|
|
341
|
+
if (typeof min === "number" && (typeof actual[key] !== "number" || actual[key] < min)) return false;
|
|
342
|
+
if (typeof max === "number" && (typeof actual[key] !== "number" || actual[key] > max)) return false;
|
|
343
|
+
}
|
|
344
|
+
if (Array.isArray(params.sizes) && !params.sizes.some((size) => isPlainRecord(size) && size.width === actual.width && size.height === actual.height))
|
|
345
|
+
return false;
|
|
346
|
+
const duration = actual.duration_ms ?? actual.duration_ms_exact;
|
|
347
|
+
const exact = params.duration_ms_exact ?? params.duration_ms;
|
|
348
|
+
if (typeof exact === "number" && duration !== exact) return false;
|
|
349
|
+
if (typeof exact !== "number" && Array.isArray(params.duration_ms_range)) {
|
|
350
|
+
const [min, max] = params.duration_ms_range;
|
|
351
|
+
if (typeof duration !== "number" || typeof min === "number" && duration < min || typeof max === "number" && duration > max)
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
return true;
|
|
355
|
+
});
|
|
356
|
+
}
|
|
302
357
|
function isDeferredClientFinalizationContext(value) {
|
|
303
358
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
304
359
|
const context = value;
|
|
@@ -1431,7 +1486,7 @@ class SingleAgentClient {
|
|
|
1431
1486
|
}
|
|
1432
1487
|
}
|
|
1433
1488
|
}
|
|
1434
|
-
rememberCanonicalProductRoutes(products, account, authoritativeProducts) {
|
|
1489
|
+
rememberCanonicalProductRoutes(products, account, authoritativeProducts, evidence) {
|
|
1435
1490
|
this.invalidateCanonicalProductRoutes(authoritativeProducts ?? products, account);
|
|
1436
1491
|
const accountScope = this.canonicalAccountScope(account);
|
|
1437
1492
|
const declaredOptions = authoritativeProducts ? this.sellerDeclaredFormatOptions(authoritativeProducts) : void 0;
|
|
@@ -1451,12 +1506,15 @@ class SingleAgentClient {
|
|
|
1451
1506
|
const refs = legacyFormatRefsForDeclaration(option);
|
|
1452
1507
|
const declared = declaredOptions ? declaredOptions.get(product.product_id)?.some((declaredRef) => this.sameCanonicalOptionRef(declaredRef, ref)) : sellerDeclaredFormatOption(option);
|
|
1453
1508
|
if (declared !== void 0) rememberSellerDeclaredFormatOption(option, declared);
|
|
1509
|
+
if (declared === true && evidence)
|
|
1510
|
+
rememberSellerFormatEvidence(option, { ...evidence, productId: product.product_id });
|
|
1454
1511
|
this.rememberCanonicalLegacyRoute(this.canonicalLegacyRouteKey(account, product.product_id, ref), {
|
|
1455
1512
|
kind: "product",
|
|
1456
1513
|
accountScope,
|
|
1457
1514
|
productId: product.product_id,
|
|
1458
1515
|
optionRef: ref,
|
|
1459
1516
|
refs,
|
|
1517
|
+
...declared === true && sellerFormatEvidence(option) ? { declaration: structuredCloneWithLegacyCreativeMetadata(option) } : {},
|
|
1460
1518
|
...declared === false ? { undeclaredSelector: undeclaredFormatOptionSelector(option) } : {}
|
|
1461
1519
|
});
|
|
1462
1520
|
}
|
|
@@ -4666,6 +4724,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4666
4724
|
}
|
|
4667
4725
|
}
|
|
4668
4726
|
const conditionalSnapshot = skipCacheRead ? void 0 : cache?.read(cacheScope, cacheParams, true);
|
|
4727
|
+
const productEvidence = this.usesScopedDiscoveryTransport(
|
|
4728
|
+
effectiveOptions
|
|
4729
|
+
) ? void 0 : {
|
|
4730
|
+
scopeKey: this.getCapabilityEvidenceScope().scopeKey,
|
|
4731
|
+
accountScope: this.canonicalAccountScope(account),
|
|
4732
|
+
expiresAt: Date.now() + resolveAgentDiscoveryTtlMs(this.config.discoveryCache?.ttlMs)
|
|
4733
|
+
};
|
|
4669
4734
|
const result = await this.executeAndHandle(
|
|
4670
4735
|
"get_products",
|
|
4671
4736
|
"onGetProductsStatusChange",
|
|
@@ -4678,7 +4743,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4678
4743
|
projectionCatalogs: projectionCatalogs ?? this.config.projectionCatalogs
|
|
4679
4744
|
});
|
|
4680
4745
|
const authoritativeProducts = Array.isArray(data.products) ? data.products : response.products;
|
|
4681
|
-
this.rememberCanonicalProductRoutes(response.products, account, authoritativeProducts);
|
|
4746
|
+
this.rememberCanonicalProductRoutes(response.products, account, authoritativeProducts, productEvidence);
|
|
4682
4747
|
const { _message: _dropLegacyMessage, ...canonical } = response;
|
|
4683
4748
|
void _dropLegacyMessage;
|
|
4684
4749
|
return { ...canonical, projection: { diagnostics } };
|
|
@@ -4689,7 +4754,9 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4689
4754
|
);
|
|
4690
4755
|
const finishCache = async (completed) => {
|
|
4691
4756
|
if (!cache) return completed;
|
|
4692
|
-
const cachedResult = cache.write(cacheScope, cacheParams, completed, conditionalSnapshot)
|
|
4757
|
+
const cachedResult = cache.write(cacheScope, cacheParams, completed, conditionalSnapshot, (materialized) => {
|
|
4758
|
+
this.rememberCanonicalProductRoutes(materialized.data?.products ?? [], account, void 0, productEvidence);
|
|
4759
|
+
});
|
|
4693
4760
|
if (cachedResult.success && cachedResult.status === "completed") {
|
|
4694
4761
|
if (!skipCacheRead && cacheParams.if_wholesale_feed_version === void 0 && cacheParams.if_pricing_version === void 0 && cachedResult.data.unchanged === true) {
|
|
4695
4762
|
return this.getProducts(params, inputHandler, {
|
|
@@ -4849,7 +4916,12 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4849
4916
|
if (hasCreativeFormatData) {
|
|
4850
4917
|
this.validateBeforeCreativeCapabilityProbe("create_media_buy", params, taskOptions);
|
|
4851
4918
|
}
|
|
4852
|
-
const wireMode = hasCreativeFormatData ? await this.
|
|
4919
|
+
const wireMode = hasCreativeFormatData ? await this.resolveCreativeWireMode(
|
|
4920
|
+
"create_media_buy",
|
|
4921
|
+
taskOptions,
|
|
4922
|
+
true,
|
|
4923
|
+
() => this.productOptionsSupportCanonicalWire("create_media_buy", params, [], options)
|
|
4924
|
+
) : "canonical";
|
|
4853
4925
|
const wireParams = params;
|
|
4854
4926
|
const result = await this.executeAndHandle(
|
|
4855
4927
|
"create_media_buy",
|
|
@@ -4937,7 +5009,12 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4937
5009
|
if (hasCreativeFormatData) {
|
|
4938
5010
|
this.validateBeforeCreativeCapabilityProbe("update_media_buy", params, taskOptions);
|
|
4939
5011
|
}
|
|
4940
|
-
const wireMode = hasCreativeFormatData ? await this.
|
|
5012
|
+
const wireMode = hasCreativeFormatData ? await this.resolveCreativeWireMode(
|
|
5013
|
+
"update_media_buy",
|
|
5014
|
+
taskOptions,
|
|
5015
|
+
true,
|
|
5016
|
+
() => this.productOptionsSupportCanonicalWire("update_media_buy", params, [], options)
|
|
5017
|
+
) : "canonical";
|
|
4941
5018
|
const result = await this.executeAndHandle(
|
|
4942
5019
|
"update_media_buy",
|
|
4943
5020
|
"onUpdateMediaBuyStatusChange",
|
|
@@ -5026,7 +5103,6 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5026
5103
|
projectionCatalogs ?? this.config.projectionCatalogs
|
|
5027
5104
|
);
|
|
5028
5105
|
this.validateBeforeCreativeCapabilityProbe("sync_creatives", params, taskOptions);
|
|
5029
|
-
const wireMode = await this.resolveCreativeFormatWireMode("sync_creatives", taskOptions);
|
|
5030
5106
|
const configuredSelectorContainers = [
|
|
5031
5107
|
...creativeFormatProjection?.selectorContainers ?? []
|
|
5032
5108
|
];
|
|
@@ -5038,10 +5114,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5038
5114
|
const assignmentPackageContainers = Array.isArray(params.assignments) ? params.assignments.flatMap(
|
|
5039
5115
|
(assignment) => typeof assignment.package_id === "string" && !configuredPackageIds.has(assignment.package_id) ? [{ package_id: assignment.package_id }] : []
|
|
5040
5116
|
) : [];
|
|
5117
|
+
const selectorContainers = [...configuredSelectorContainers, ...assignmentPackageContainers];
|
|
5118
|
+
const wireMode = await this.resolveCreativeWireMode(
|
|
5119
|
+
"sync_creatives",
|
|
5120
|
+
taskOptions,
|
|
5121
|
+
true,
|
|
5122
|
+
() => this.productOptionsSupportCanonicalWire("sync_creatives", params, selectorContainers, options)
|
|
5123
|
+
);
|
|
5041
5124
|
const wireParams = this.projectUndeclaredFormatOptions(
|
|
5042
5125
|
projectSyncCreativesForDelivery(
|
|
5043
5126
|
params,
|
|
5044
|
-
|
|
5127
|
+
selectorContainers,
|
|
5045
5128
|
wireMode,
|
|
5046
5129
|
effectiveLegacyFormatConverter,
|
|
5047
5130
|
effectiveCanonicalFormatLegacyResolver
|
|
@@ -5081,16 +5164,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5081
5164
|
* sending a mutation. Discovers capabilities and the current tool's input
|
|
5082
5165
|
* schema, or reuses fresh cached/primed evidence, with this client's wire pin.
|
|
5083
5166
|
*
|
|
5084
|
-
* `unknown`
|
|
5085
|
-
*
|
|
5086
|
-
*
|
|
5167
|
+
* This context-free check returns `unknown` when capabilities and schema do
|
|
5168
|
+
* not establish support. A write to a proven 3.1 seller can still select
|
|
5169
|
+
* canonical delivery from matching seller-advertised product options;
|
|
5170
|
+
* otherwise projection requires an unambiguous legacy reference.
|
|
5087
5171
|
* Conflicting evidence and unproven support with a 3.2+ buyer pin throw
|
|
5088
5172
|
* `CreativeFormatCapabilityError`, just as they do during a write.
|
|
5089
5173
|
*/
|
|
5090
5174
|
async resolveCreativeFormatWireMode(taskType, options) {
|
|
5091
5175
|
return this.resolveCreativeWireMode(taskType, options, true);
|
|
5092
5176
|
}
|
|
5093
|
-
async resolveCreativeWireMode(taskType, options, canRediscover) {
|
|
5177
|
+
async resolveCreativeWireMode(taskType, options, canRediscover, matchingProductOptions) {
|
|
5094
5178
|
const discoveryContext = {};
|
|
5095
5179
|
const capabilities = await this.getCapabilities({
|
|
5096
5180
|
...options,
|
|
@@ -5109,13 +5193,16 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5109
5193
|
`Seller capability and ${taskType} input schema disagree about canonical creative support`
|
|
5110
5194
|
);
|
|
5111
5195
|
}
|
|
5112
|
-
|
|
5196
|
+
let resolved = declared !== "unknown" ? declared : schema;
|
|
5197
|
+
if (resolved === "unknown" && canUseProductOptionsForCreativeWire(capabilities, wireRelease) && matchingProductOptions?.()) {
|
|
5198
|
+
resolved = "canonical";
|
|
5199
|
+
}
|
|
5113
5200
|
const release = /^v?(\d+)\.(\d+)(?:\.|-|$)/.exec(wireRelease.trim());
|
|
5114
5201
|
const canonicalRequiredByBuyerPin = release !== null && (Number(release[1]) > 3 || Number(release[1]) === 3 && Number(release[2]) >= 2);
|
|
5115
5202
|
if (resolved === "unknown" && canonicalRequiredByBuyerPin) {
|
|
5116
5203
|
if (canRediscover && !usesScopedFetch && this.normalizedAgent.protocol === "mcp" && this.capabilitiesFromSharedCache && toolSchemas?.has(taskType) && !toolInputSchemasByProperties.has(toolSchemas)) {
|
|
5117
5204
|
await this.invalidateDiscoveryCache(options);
|
|
5118
|
-
return this.resolveCreativeWireMode(taskType, options, false);
|
|
5205
|
+
return this.resolveCreativeWireMode(taskType, options, false, matchingProductOptions);
|
|
5119
5206
|
}
|
|
5120
5207
|
throw new CreativeFormatCapabilityError(
|
|
5121
5208
|
`Cannot prove which AdCP release the seller serves for ${taskType}; a 3.2+ client will not guess a legacy creative wire shape`
|
|
@@ -5123,6 +5210,115 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5123
5210
|
}
|
|
5124
5211
|
return resolved;
|
|
5125
5212
|
}
|
|
5213
|
+
usesScopedDiscoveryTransport(options) {
|
|
5214
|
+
return normalizeTransportOptions(options?.transport ?? this.config.transport)?.trustedFetchFn !== void 0;
|
|
5215
|
+
}
|
|
5216
|
+
/** Product evidence applies to this request only; it must never prime a tool-wide capability. */
|
|
5217
|
+
productOptionsSupportCanonicalWire(taskType, request, selectorContainers = [], options) {
|
|
5218
|
+
if (!isPlainRecord(request) || this.usesScopedDiscoveryTransport(options)) return false;
|
|
5219
|
+
const scopeKey = this.getCapabilityEvidenceScope().scopeKey;
|
|
5220
|
+
const accountScope = this.canonicalAccountScope(request.account);
|
|
5221
|
+
const optionRef = (value) => {
|
|
5222
|
+
if (!isPlainRecord(value) || typeof value.format_option_id !== "string" || !value.format_option_id) {
|
|
5223
|
+
return void 0;
|
|
5224
|
+
}
|
|
5225
|
+
if (typeof value.publisher_domain === "string") {
|
|
5226
|
+
return {
|
|
5227
|
+
scope: "publisher",
|
|
5228
|
+
publisher_domain: value.publisher_domain,
|
|
5229
|
+
format_option_id: value.format_option_id
|
|
5230
|
+
};
|
|
5231
|
+
}
|
|
5232
|
+
if (value.scope !== void 0 && value.scope !== "product") return void 0;
|
|
5233
|
+
return { scope: "product", format_option_id: value.format_option_id };
|
|
5234
|
+
};
|
|
5235
|
+
const accepts = (container, creative, depth = 0) => {
|
|
5236
|
+
if (depth > 32) return false;
|
|
5237
|
+
if (Array.isArray(container.selector_containers)) {
|
|
5238
|
+
return container.selector_containers.length > 0 && container.selector_containers.every((nested) => accepts(nested, creative, depth + 1));
|
|
5239
|
+
}
|
|
5240
|
+
const refs = Array.isArray(container.format_option_refs) ? container.format_option_refs.map(optionRef) : [];
|
|
5241
|
+
if (refs.some((ref) => ref === void 0)) return false;
|
|
5242
|
+
const creativeRef = isPlainRecord(creative) ? optionRef(creative.format_option_ref) : void 0;
|
|
5243
|
+
if (isPlainRecord(creative) && creative.format_option_ref !== void 0 && !creativeRef) return false;
|
|
5244
|
+
const isSellerDeclaration = (value) => {
|
|
5245
|
+
if (!isPlainRecord(value) || sellerDeclaredFormatOption(value) !== true || isSynthesizedFormatOption(value)) {
|
|
5246
|
+
return false;
|
|
5247
|
+
}
|
|
5248
|
+
const evidence2 = sellerFormatEvidence(value);
|
|
5249
|
+
if (!evidence2 || evidence2.scopeKey !== scopeKey || typeof container.product_id === "string" && evidence2.productId !== container.product_id || evidence2.expiresAt <= Date.now() || evidence2.accountScope !== accountScope && evidence2.accountScope !== "none")
|
|
5250
|
+
return false;
|
|
5251
|
+
const ref = optionRef(value);
|
|
5252
|
+
if (ref && formatOptionOriginFromRoutes(
|
|
5253
|
+
options?.canonicalFormatLegacyResolver,
|
|
5254
|
+
ref,
|
|
5255
|
+
typeof container.product_id === "string" ? container.product_id : void 0
|
|
5256
|
+
)?.seller_declared === false)
|
|
5257
|
+
return false;
|
|
5258
|
+
return !ref || typeof container.product_id !== "string" || this.cachedFormatOptionOrigin(request.account, ref, container.product_id)?.seller_declared !== false;
|
|
5259
|
+
};
|
|
5260
|
+
const declarations = [
|
|
5261
|
+
...(Array.isArray(container.format_options) ? container.format_options : []).filter(isSellerDeclaration),
|
|
5262
|
+
...selectedFormatOptions(container).filter(isSellerDeclaration)
|
|
5263
|
+
];
|
|
5264
|
+
if (typeof container.product_id === "string") {
|
|
5265
|
+
for (const ref of [...refs, ...creativeRef ? [creativeRef] : []]) {
|
|
5266
|
+
if (!ref) continue;
|
|
5267
|
+
const route = this.routeForOption(request.account, container.product_id, ref);
|
|
5268
|
+
if (route?.kind === "product" && route.declaration && isSellerDeclaration(route.declaration))
|
|
5269
|
+
declarations.push(route.declaration);
|
|
5270
|
+
}
|
|
5271
|
+
}
|
|
5272
|
+
const available = declarations.filter((declaration) => declaration.experimental !== true);
|
|
5273
|
+
const matchesRef = (declaration, ref) => {
|
|
5274
|
+
const declaredRef = optionRef(declaration);
|
|
5275
|
+
return declaredRef !== void 0 && this.sameCanonicalOptionRef(declaredRef, ref);
|
|
5276
|
+
};
|
|
5277
|
+
if (!refs.every((ref) => available.some((declaration) => matchesRef(declaration, ref)))) return false;
|
|
5278
|
+
const selected = available.filter(
|
|
5279
|
+
(declaration) => refs.length === 0 || refs.some((ref) => matchesRef(declaration, ref))
|
|
5280
|
+
);
|
|
5281
|
+
if (creative === void 0) return refs.length > 0 && selected.length > 0;
|
|
5282
|
+
if (!isPlainRecord(creative) || typeof creative.format_kind !== "string" || creative.format_id !== void 0)
|
|
5283
|
+
return false;
|
|
5284
|
+
return selected.some(
|
|
5285
|
+
(declaration) => declaration.format_kind === creative.format_kind && (!creativeRef || matchesRef(declaration, creativeRef)) && creativeMatchesProductOption(creative, declaration)
|
|
5286
|
+
);
|
|
5287
|
+
};
|
|
5288
|
+
if (taskType === "sync_creatives") {
|
|
5289
|
+
if (!Array.isArray(request.creatives) || request.creatives.length === 0) return false;
|
|
5290
|
+
const creatives = request.creatives;
|
|
5291
|
+
const assignments = Array.isArray(request.assignments) ? request.assignments : [];
|
|
5292
|
+
if (!assignments.every(
|
|
5293
|
+
(value) => isPlainRecord(value) && typeof value.package_id === "string" && typeof value.creative_id === "string" && creatives.some((creative) => isPlainRecord(creative) && creative.creative_id === value.creative_id)
|
|
5294
|
+
))
|
|
5295
|
+
return false;
|
|
5296
|
+
return creatives.every((creative) => {
|
|
5297
|
+
if (!isPlainRecord(creative)) return false;
|
|
5298
|
+
const assigned = new Set(
|
|
5299
|
+
assignments.flatMap(
|
|
5300
|
+
(value) => isPlainRecord(value) && value.creative_id === creative.creative_id && typeof value.package_id === "string" ? [value.package_id] : []
|
|
5301
|
+
)
|
|
5302
|
+
);
|
|
5303
|
+
const relevant = assigned.size === 0 ? selectorContainers : selectorContainers.filter(
|
|
5304
|
+
(container) => typeof container.package_id === "string" && assigned.has(container.package_id)
|
|
5305
|
+
);
|
|
5306
|
+
return relevant.length > 0 && [...assigned].every((id) => relevant.some((container) => container.package_id === id)) && relevant.every((container) => accepts(container, creative));
|
|
5307
|
+
});
|
|
5308
|
+
}
|
|
5309
|
+
const packages = ["packages", "new_packages"].flatMap((key) => Array.isArray(request[key]) ? request[key] : []);
|
|
5310
|
+
let evidence = false;
|
|
5311
|
+
return packages.length > 0 && packages.every((pkg) => {
|
|
5312
|
+
if (!isPlainRecord(pkg)) return false;
|
|
5313
|
+
const creatives = Array.isArray(pkg.creatives) ? pkg.creatives : [];
|
|
5314
|
+
const hasSelectors = Array.isArray(pkg.format_option_refs) && pkg.format_option_refs.length > 0;
|
|
5315
|
+
if (!hasSelectors && creatives.length === 0) {
|
|
5316
|
+
return pkg.format_kind === void 0 && pkg.format_ids === void 0;
|
|
5317
|
+
}
|
|
5318
|
+
evidence = true;
|
|
5319
|
+
return (!hasSelectors || accepts(pkg)) && creatives.every((creative) => accepts(pkg, creative));
|
|
5320
|
+
}) && evidence;
|
|
5321
|
+
}
|
|
5126
5322
|
/** Validate malformed creative payloads before capability discovery can perform I/O. */
|
|
5127
5323
|
validateBeforeCreativeCapabilityProbe(taskType, params, options) {
|
|
5128
5324
|
if (options.skipIdempotencyAutoInject || options.skipAccountValidation || options.skipRequestValidation) return;
|
|
@@ -4398,41 +4398,22 @@ class TaskExecutor {
|
|
|
4398
4398
|
const mode = this.responseValidationMode;
|
|
4399
4399
|
const logViolations = this.config.logSchemaViolations !== false;
|
|
4400
4400
|
try {
|
|
4401
|
-
|
|
4402
|
-
if (taskName === "get_adcp_capabilities" &&
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
const errorStrings = outcome.issues.map((i) => `${i.pointer}: ${i.message}`);
|
|
4409
|
-
if (logViolations) {
|
|
4410
|
-
debugLogs.push({
|
|
4411
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4412
|
-
type: mode === "strict" ? "error" : "warning",
|
|
4413
|
-
message: `Schema validation ${mode === "strict" ? "failed" : "warning"} for ${taskName}: ${(0, import_schema_validator.formatIssues)(
|
|
4414
|
-
outcome.issues
|
|
4415
|
-
)}`,
|
|
4416
|
-
errors: errorStrings,
|
|
4417
|
-
issues: outcome.issues,
|
|
4418
|
-
schemaVariant: outcome.variant,
|
|
4419
|
-
schemaVersion: validationVersion,
|
|
4420
|
-
mode
|
|
4421
|
-
});
|
|
4422
|
-
}
|
|
4423
|
-
if (mode === "warn") {
|
|
4424
|
-
if (logViolations) {
|
|
4425
|
-
console.warn(
|
|
4426
|
-
`Schema validation failed for ${taskName} against AdCP ${validationVersion} (non-blocking):`,
|
|
4427
|
-
errorStrings
|
|
4428
|
-
);
|
|
4429
|
-
}
|
|
4430
|
-
return { valid: true, errors: [] };
|
|
4431
|
-
}
|
|
4432
|
-
if (logViolations) {
|
|
4433
|
-
console.error(`Schema validation failed for ${taskName} against AdCP ${validationVersion}:`, errorStrings);
|
|
4401
|
+
const pinnedValidationVersion = (serverVersion ?? this.lastKnownServerVersion) === "v2" ? "v2.5" : this.responseAdcpVersionForValidation() ?? this.config.adcpVersion ?? import_version.ADCP_VERSION;
|
|
4402
|
+
if (taskName === "get_adcp_capabilities" && pinnedValidationVersion !== "v2.5") {
|
|
4403
|
+
return (0, import_schema_loader.withServedValidationVersion)(
|
|
4404
|
+
response,
|
|
4405
|
+
pinnedValidationVersion,
|
|
4406
|
+
(validationVersion) => this.validateResponseSchemaAgainst(response, taskName, debugLogs, mode, logViolations, validationVersion)
|
|
4407
|
+
);
|
|
4434
4408
|
}
|
|
4435
|
-
return
|
|
4409
|
+
return this.validateResponseSchemaAgainst(
|
|
4410
|
+
response,
|
|
4411
|
+
taskName,
|
|
4412
|
+
debugLogs,
|
|
4413
|
+
mode,
|
|
4414
|
+
logViolations,
|
|
4415
|
+
pinnedValidationVersion
|
|
4416
|
+
);
|
|
4436
4417
|
} catch (error) {
|
|
4437
4418
|
const errorMessage = error instanceof Error ? error.message : "unknown error";
|
|
4438
4419
|
console.error("Error during schema validation:", errorMessage);
|
|
@@ -4442,6 +4423,39 @@ class TaskExecutor {
|
|
|
4442
4423
|
};
|
|
4443
4424
|
}
|
|
4444
4425
|
}
|
|
4426
|
+
validateResponseSchemaAgainst(response, taskName, debugLogs, mode, logViolations, validationVersion) {
|
|
4427
|
+
const normalizedResponse = this.normalizeResponseForValidation(response, taskName, validationVersion === "v2.5");
|
|
4428
|
+
const outcome = (0, import_client_hooks.validateIncomingResponse)(taskName, normalizedResponse, mode, void 0, validationVersion);
|
|
4429
|
+
if (outcome.valid) return { valid: true, errors: [] };
|
|
4430
|
+
const errorStrings = outcome.issues.map((i) => `${i.pointer}: ${i.message}`);
|
|
4431
|
+
if (logViolations) {
|
|
4432
|
+
debugLogs.push({
|
|
4433
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4434
|
+
type: mode === "strict" ? "error" : "warning",
|
|
4435
|
+
message: `Schema validation ${mode === "strict" ? "failed" : "warning"} for ${taskName}: ${(0, import_schema_validator.formatIssues)(
|
|
4436
|
+
outcome.issues
|
|
4437
|
+
)}`,
|
|
4438
|
+
errors: errorStrings,
|
|
4439
|
+
issues: outcome.issues,
|
|
4440
|
+
schemaVariant: outcome.variant,
|
|
4441
|
+
schemaVersion: validationVersion,
|
|
4442
|
+
mode
|
|
4443
|
+
});
|
|
4444
|
+
}
|
|
4445
|
+
if (mode === "warn") {
|
|
4446
|
+
if (logViolations) {
|
|
4447
|
+
console.warn(
|
|
4448
|
+
`Schema validation failed for ${taskName} against AdCP ${validationVersion} (non-blocking):`,
|
|
4449
|
+
errorStrings
|
|
4450
|
+
);
|
|
4451
|
+
}
|
|
4452
|
+
return { valid: true, errors: [] };
|
|
4453
|
+
}
|
|
4454
|
+
if (logViolations) {
|
|
4455
|
+
console.error(`Schema validation failed for ${taskName} against AdCP ${validationVersion}:`, errorStrings);
|
|
4456
|
+
}
|
|
4457
|
+
return { valid: false, errors: errorStrings };
|
|
4458
|
+
}
|
|
4445
4459
|
responseAdcpVersionForValidation() {
|
|
4446
4460
|
if (this.config.versionEnvelope === "major-only") return "3.0";
|
|
4447
4461
|
return void 0;
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
resolveValidationModes
|
|
16
16
|
} from "../validation/client-hooks.mjs";
|
|
17
17
|
import { formatIssues } from "../validation/schema-validator.mjs";
|
|
18
|
-
import {
|
|
18
|
+
import { withServedValidationVersion } from "../validation/schema-loader.mjs";
|
|
19
19
|
import { ADCP_VERSION } from "../version.mjs";
|
|
20
20
|
import { unwrapProtocolResponse, isAdcpOperationSuccess } from "../utils/response-unwrapper.mjs";
|
|
21
21
|
import { extractAdcpErrorInfo, extractCorrelationId } from "../utils/error-extraction.mjs";
|
|
@@ -4371,41 +4371,22 @@ class TaskExecutor {
|
|
|
4371
4371
|
const mode = this.responseValidationMode;
|
|
4372
4372
|
const logViolations = this.config.logSchemaViolations !== false;
|
|
4373
4373
|
try {
|
|
4374
|
-
|
|
4375
|
-
if (taskName === "get_adcp_capabilities" &&
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
const errorStrings = outcome.issues.map((i) => `${i.pointer}: ${i.message}`);
|
|
4382
|
-
if (logViolations) {
|
|
4383
|
-
debugLogs.push({
|
|
4384
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4385
|
-
type: mode === "strict" ? "error" : "warning",
|
|
4386
|
-
message: `Schema validation ${mode === "strict" ? "failed" : "warning"} for ${taskName}: ${formatIssues(
|
|
4387
|
-
outcome.issues
|
|
4388
|
-
)}`,
|
|
4389
|
-
errors: errorStrings,
|
|
4390
|
-
issues: outcome.issues,
|
|
4391
|
-
schemaVariant: outcome.variant,
|
|
4392
|
-
schemaVersion: validationVersion,
|
|
4393
|
-
mode
|
|
4394
|
-
});
|
|
4395
|
-
}
|
|
4396
|
-
if (mode === "warn") {
|
|
4397
|
-
if (logViolations) {
|
|
4398
|
-
console.warn(
|
|
4399
|
-
`Schema validation failed for ${taskName} against AdCP ${validationVersion} (non-blocking):`,
|
|
4400
|
-
errorStrings
|
|
4401
|
-
);
|
|
4402
|
-
}
|
|
4403
|
-
return { valid: true, errors: [] };
|
|
4404
|
-
}
|
|
4405
|
-
if (logViolations) {
|
|
4406
|
-
console.error(`Schema validation failed for ${taskName} against AdCP ${validationVersion}:`, errorStrings);
|
|
4374
|
+
const pinnedValidationVersion = (serverVersion ?? this.lastKnownServerVersion) === "v2" ? "v2.5" : this.responseAdcpVersionForValidation() ?? this.config.adcpVersion ?? ADCP_VERSION;
|
|
4375
|
+
if (taskName === "get_adcp_capabilities" && pinnedValidationVersion !== "v2.5") {
|
|
4376
|
+
return withServedValidationVersion(
|
|
4377
|
+
response,
|
|
4378
|
+
pinnedValidationVersion,
|
|
4379
|
+
(validationVersion) => this.validateResponseSchemaAgainst(response, taskName, debugLogs, mode, logViolations, validationVersion)
|
|
4380
|
+
);
|
|
4407
4381
|
}
|
|
4408
|
-
return
|
|
4382
|
+
return this.validateResponseSchemaAgainst(
|
|
4383
|
+
response,
|
|
4384
|
+
taskName,
|
|
4385
|
+
debugLogs,
|
|
4386
|
+
mode,
|
|
4387
|
+
logViolations,
|
|
4388
|
+
pinnedValidationVersion
|
|
4389
|
+
);
|
|
4409
4390
|
} catch (error) {
|
|
4410
4391
|
const errorMessage = error instanceof Error ? error.message : "unknown error";
|
|
4411
4392
|
console.error("Error during schema validation:", errorMessage);
|
|
@@ -4415,6 +4396,39 @@ class TaskExecutor {
|
|
|
4415
4396
|
};
|
|
4416
4397
|
}
|
|
4417
4398
|
}
|
|
4399
|
+
validateResponseSchemaAgainst(response, taskName, debugLogs, mode, logViolations, validationVersion) {
|
|
4400
|
+
const normalizedResponse = this.normalizeResponseForValidation(response, taskName, validationVersion === "v2.5");
|
|
4401
|
+
const outcome = validateIncomingResponse(taskName, normalizedResponse, mode, void 0, validationVersion);
|
|
4402
|
+
if (outcome.valid) return { valid: true, errors: [] };
|
|
4403
|
+
const errorStrings = outcome.issues.map((i) => `${i.pointer}: ${i.message}`);
|
|
4404
|
+
if (logViolations) {
|
|
4405
|
+
debugLogs.push({
|
|
4406
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4407
|
+
type: mode === "strict" ? "error" : "warning",
|
|
4408
|
+
message: `Schema validation ${mode === "strict" ? "failed" : "warning"} for ${taskName}: ${formatIssues(
|
|
4409
|
+
outcome.issues
|
|
4410
|
+
)}`,
|
|
4411
|
+
errors: errorStrings,
|
|
4412
|
+
issues: outcome.issues,
|
|
4413
|
+
schemaVariant: outcome.variant,
|
|
4414
|
+
schemaVersion: validationVersion,
|
|
4415
|
+
mode
|
|
4416
|
+
});
|
|
4417
|
+
}
|
|
4418
|
+
if (mode === "warn") {
|
|
4419
|
+
if (logViolations) {
|
|
4420
|
+
console.warn(
|
|
4421
|
+
`Schema validation failed for ${taskName} against AdCP ${validationVersion} (non-blocking):`,
|
|
4422
|
+
errorStrings
|
|
4423
|
+
);
|
|
4424
|
+
}
|
|
4425
|
+
return { valid: true, errors: [] };
|
|
4426
|
+
}
|
|
4427
|
+
if (logViolations) {
|
|
4428
|
+
console.error(`Schema validation failed for ${taskName} against AdCP ${validationVersion}:`, errorStrings);
|
|
4429
|
+
}
|
|
4430
|
+
return { valid: false, errors: errorStrings };
|
|
4431
|
+
}
|
|
4418
4432
|
responseAdcpVersionForValidation() {
|
|
4419
4433
|
if (this.config.versionEnvelope === "major-only") return "3.0";
|
|
4420
4434
|
return void 0;
|
|
@@ -12,7 +12,9 @@ export declare class ProductCache {
|
|
|
12
12
|
private key;
|
|
13
13
|
read<T>(scope: string, params: Record<string, unknown>, allowExpired?: boolean): TaskResult<T> | undefined;
|
|
14
14
|
conditionalParams(scope: string, params: Record<string, unknown>): Record<string, unknown>;
|
|
15
|
-
write<T>(scope: string, params: Record<string, unknown>, result: TaskResult<T>, conditionalSnapshot?: TaskResult<T
|
|
15
|
+
write<T>(scope: string, params: Record<string, unknown>, result: TaskResult<T>, conditionalSnapshot?: TaskResult<T>,
|
|
16
|
+
/** @internal Refresh private discovery evidence before a confirmed snapshot is cloned into storage. */
|
|
17
|
+
onRevalidated?: (materialized: TaskResult<T>) => void): TaskResult<T>;
|
|
16
18
|
clear(): void;
|
|
17
19
|
}
|
|
18
20
|
export declare function createProductCache(options?: ProductCacheOptions): ProductCache;
|
|
@@ -12,7 +12,9 @@ export declare class ProductCache {
|
|
|
12
12
|
private key;
|
|
13
13
|
read<T>(scope: string, params: Record<string, unknown>, allowExpired?: boolean): TaskResult<T> | undefined;
|
|
14
14
|
conditionalParams(scope: string, params: Record<string, unknown>): Record<string, unknown>;
|
|
15
|
-
write<T>(scope: string, params: Record<string, unknown>, result: TaskResult<T>, conditionalSnapshot?: TaskResult<T
|
|
15
|
+
write<T>(scope: string, params: Record<string, unknown>, result: TaskResult<T>, conditionalSnapshot?: TaskResult<T>,
|
|
16
|
+
/** @internal Refresh private discovery evidence before a confirmed snapshot is cloned into storage. */
|
|
17
|
+
onRevalidated?: (materialized: TaskResult<T>) => void): TaskResult<T>;
|
|
16
18
|
clear(): void;
|
|
17
19
|
}
|
|
18
20
|
export declare function createProductCache(options?: ProductCacheOptions): ProductCache;
|
|
@@ -86,7 +86,7 @@ class ProductCache {
|
|
|
86
86
|
...typeof data.pricing_version === "string" && { if_pricing_version: data.pricing_version }
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
|
-
write(scope, params, result, conditionalSnapshot) {
|
|
89
|
+
write(scope, params, result, conditionalSnapshot, onRevalidated) {
|
|
90
90
|
const key = this.key(scope, params);
|
|
91
91
|
if (!key) return result;
|
|
92
92
|
if (!result.success || result.status !== "completed" || !result.data || typeof result.data !== "object")
|
|
@@ -109,6 +109,7 @@ class ProductCache {
|
|
|
109
109
|
return result;
|
|
110
110
|
if (params.if_wholesale_feed_version !== void 0 || params.if_pricing_version !== void 0) return result;
|
|
111
111
|
completed = { ...result, data: (0, import_legacy_metadata.structuredCloneWithLegacyCreativeMetadata)(oldData) };
|
|
112
|
+
onRevalidated?.(completed);
|
|
112
113
|
} else if (!Array.isArray(data.products)) return result;
|
|
113
114
|
if (!this.entries.has(key) && this.entries.size >= (this.options.maxEntries ?? 1e3))
|
|
114
115
|
this.entries.delete(this.entries.keys().next().value);
|
|
@@ -62,7 +62,7 @@ class ProductCache {
|
|
|
62
62
|
...typeof data.pricing_version === "string" && { if_pricing_version: data.pricing_version }
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
-
write(scope, params, result, conditionalSnapshot) {
|
|
65
|
+
write(scope, params, result, conditionalSnapshot, onRevalidated) {
|
|
66
66
|
const key = this.key(scope, params);
|
|
67
67
|
if (!key) return result;
|
|
68
68
|
if (!result.success || result.status !== "completed" || !result.data || typeof result.data !== "object")
|
|
@@ -85,6 +85,7 @@ class ProductCache {
|
|
|
85
85
|
return result;
|
|
86
86
|
if (params.if_wholesale_feed_version !== void 0 || params.if_pricing_version !== void 0) return result;
|
|
87
87
|
completed = { ...result, data: structuredCloneWithLegacyCreativeMetadata(oldData) };
|
|
88
|
+
onRevalidated?.(completed);
|
|
88
89
|
} else if (!Array.isArray(data.products)) return result;
|
|
89
90
|
if (!this.entries.has(key) && this.entries.size >= (this.options.maxEntries ?? 1e3))
|
|
90
91
|
this.entries.delete(this.entries.keys().next().value);
|
|
@@ -144,9 +144,10 @@ export type SavePropertyRequest = Omit<RegistrySavePropertyRequest, 'authorized_
|
|
|
144
144
|
/** Response from POST /api/properties/save (200) */
|
|
145
145
|
export type SavePropertyResponse = operations['saveProperty']['responses']['200']['content']['application/json'];
|
|
146
146
|
type RegistryResolveIdentifiersRequest = NonNullable<operations['resolveIdentifiers']['requestBody']>['content']['application/json'];
|
|
147
|
-
/** Request body for POST /api/registry/resolve.
|
|
148
|
-
export type ResolveIdentifiersRequest = Omit<RegistryResolveIdentifiersRequest, 'mode'> & {
|
|
147
|
+
/** Request body for POST /api/registry/resolve. Mode and sandbox use the registry's defaults when omitted. */
|
|
148
|
+
export type ResolveIdentifiersRequest = Omit<RegistryResolveIdentifiersRequest, 'mode' | 'sandbox'> & {
|
|
149
149
|
mode?: RegistryResolveIdentifiersRequest['mode'];
|
|
150
|
+
sandbox?: RegistryResolveIdentifiersRequest['sandbox'];
|
|
150
151
|
};
|
|
151
152
|
/** Response from POST /api/registry/resolve (200) */
|
|
152
153
|
export type ResolveIdentifiersResponse = operations['resolveIdentifiers']['responses']['200']['content']['application/json'];
|