@adcp/sdk 13.0.0-rc.8 → 13.0.0-rc.9
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/roster-account-store.d.mts +9 -8
- package/dist/lib/adapters/roster-account-store.d.ts +9 -8
- package/dist/lib/adapters/roster-account-store.d.ts.map +1 -1
- package/dist/lib/adapters/roster-account-store.js +2 -1
- package/dist/lib/adapters/roster-account-store.js.map +1 -1
- package/dist/lib/adapters/roster-account-store.mjs +2 -1
- package/dist/lib/adapters/roster-account-store.mjs.map +1 -1
- package/dist/lib/net/address-guards.d.ts.map +1 -1
- package/dist/lib/net/address-guards.js +6 -0
- package/dist/lib/net/address-guards.js.map +1 -1
- package/dist/lib/net/address-guards.mjs +6 -0
- package/dist/lib/net/address-guards.mjs.map +1 -1
- package/dist/lib/net/ssrf-fetch.d.ts.map +1 -1
- package/dist/lib/net/ssrf-fetch.js +66 -53
- package/dist/lib/net/ssrf-fetch.js.map +1 -1
- package/dist/lib/net/ssrf-fetch.mjs +66 -53
- package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/account-mode.d.mts +2 -1
- package/dist/lib/server/account-mode.d.ts +2 -1
- package/dist/lib/server/account-mode.d.ts.map +1 -1
- package/dist/lib/server/account-mode.js +1 -0
- package/dist/lib/server/account-mode.js.map +1 -1
- package/dist/lib/server/account-mode.mjs +1 -0
- package/dist/lib/server/account-mode.mjs.map +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +10 -6
- package/dist/lib/server/create-adcp-server.d.ts +10 -6
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +2 -1
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +2 -1
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/decisioning/account.d.mts +16 -11
- package/dist/lib/server/decisioning/account.d.ts +16 -11
- package/dist/lib/server/decisioning/account.d.ts.map +1 -1
- package/dist/lib/server/decisioning/account.js.map +1 -1
- package/dist/lib/server/decisioning/account.mjs.map +1 -1
- package/dist/lib/server/decisioning/pagination.d.mts +2 -0
- package/dist/lib/server/decisioning/pagination.d.ts +2 -0
- package/dist/lib/server/decisioning/pagination.d.ts.map +1 -1
- package/dist/lib/server/decisioning/pagination.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.mts +20 -14
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +20 -14
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +32 -6
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +32 -6
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/sales.d.mts +16 -4
- package/dist/lib/server/decisioning/specialisms/sales.d.ts +16 -4
- package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -1
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/server/legacy/v5/index.d.mts +2 -1
- package/dist/lib/server/legacy/v5/index.d.ts +2 -1
- package/dist/lib/server/legacy/v5/index.d.ts.map +1 -1
- package/dist/lib/server/legacy/v5/index.js.map +1 -1
- package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
- package/dist/lib/testing/compliance/comply.d.mts +2 -0
- package/dist/lib/testing/compliance/comply.d.ts +2 -0
- package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
- package/dist/lib/testing/compliance/comply.js +45 -14
- package/dist/lib/testing/compliance/comply.js.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +45 -14
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/compliance/index.d.mts +1 -1
- package/dist/lib/testing/compliance/index.d.ts +1 -1
- package/dist/lib/testing/compliance/index.d.ts.map +1 -1
- package/dist/lib/testing/compliance/index.js.map +1 -1
- package/dist/lib/testing/compliance/index.mjs.map +1 -1
- package/dist/lib/testing/compliance/storyboard-tracks.d.ts.map +1 -1
- package/dist/lib/testing/compliance/storyboard-tracks.js +9 -1
- package/dist/lib/testing/compliance/storyboard-tracks.js.map +1 -1
- package/dist/lib/testing/compliance/storyboard-tracks.mjs +9 -1
- package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
- package/dist/lib/testing/compliance/types.d.mts +26 -25
- package/dist/lib/testing/compliance/types.d.ts +26 -25
- package/dist/lib/testing/compliance/types.d.ts.map +1 -1
- package/dist/lib/testing/compliance/types.js.map +1 -1
- package/dist/lib/testing/index.d.mts +2 -2
- package/dist/lib/testing/index.d.ts +2 -2
- package/dist/lib/testing/index.d.ts.map +1 -1
- package/dist/lib/testing/index.js +16 -0
- package/dist/lib/testing/index.js.map +1 -1
- package/dist/lib/testing/index.mjs +16 -0
- package/dist/lib/testing/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.js +20 -12
- package/dist/lib/testing/scenarios/media-buy.js.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.mjs +20 -12
- package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
- package/dist/lib/testing/storyboard/creative-assets.d.mts +23 -0
- package/dist/lib/testing/storyboard/creative-assets.d.ts +23 -0
- package/dist/lib/testing/storyboard/creative-assets.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/creative-assets.js +322 -45
- package/dist/lib/testing/storyboard/creative-assets.js.map +1 -1
- package/dist/lib/testing/storyboard/creative-assets.mjs +321 -45
- package/dist/lib/testing/storyboard/creative-assets.mjs.map +1 -1
- package/dist/lib/testing/storyboard/index.d.mts +4 -1
- package/dist/lib/testing/storyboard/index.d.ts +4 -1
- package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/index.js +20 -0
- package/dist/lib/testing/storyboard/index.js.map +1 -1
- package/dist/lib/testing/storyboard/index.mjs +19 -0
- package/dist/lib/testing/storyboard/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.d.mts +21 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.d.ts +22 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.js +668 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.js.map +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.mjs +638 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.mjs.map +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/index.d.mts +5 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/index.d.ts +6 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/index.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/index.js +44 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/index.js.map +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/index.mjs +20 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/index.mjs.map +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/types.d.mts +38 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/types.d.ts +39 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/types.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/types.js +17 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/types.js.map +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/types.mjs +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/types.mjs.map +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.d.mts +32 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.d.ts +33 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.js +105 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.js.map +1 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.mjs +80 -0
- package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.mjs.map +1 -0
- package/dist/lib/testing/storyboard/probes.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/probes.js +2 -1
- package/dist/lib/testing/storyboard/probes.js.map +1 -1
- package/dist/lib/testing/storyboard/probes.mjs +2 -1
- package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +382 -69
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +387 -70
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/seeding.js +3 -1
- package/dist/lib/testing/storyboard/seeding.js.map +1 -1
- package/dist/lib/testing/storyboard/seeding.mjs +3 -1
- package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
- package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/task-map.js +16 -2
- package/dist/lib/testing/storyboard/task-map.js.map +1 -1
- package/dist/lib/testing/storyboard/task-map.mjs +16 -2
- package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
- package/dist/lib/testing/storyboard/trusted-match-context-replay.d.mts +11 -0
- package/dist/lib/testing/storyboard/trusted-match-context-replay.d.ts +12 -0
- package/dist/lib/testing/storyboard/trusted-match-context-replay.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/trusted-match-context-replay.js +340 -0
- package/dist/lib/testing/storyboard/trusted-match-context-replay.js.map +1 -0
- package/dist/lib/testing/storyboard/trusted-match-context-replay.mjs +316 -0
- package/dist/lib/testing/storyboard/trusted-match-context-replay.mjs.map +1 -0
- package/dist/lib/testing/storyboard/types.d.mts +84 -15
- package/dist/lib/testing/storyboard/types.d.ts +84 -15
- package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/types.js +2 -0
- package/dist/lib/testing/storyboard/types.js.map +1 -1
- package/dist/lib/testing/storyboard/types.mjs +2 -0
- package/dist/lib/testing/storyboard/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.d.mts +3 -0
- package/dist/lib/testing/storyboard/validations.d.ts +3 -0
- package/dist/lib/testing/storyboard/validations.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/validations.js +64 -24
- package/dist/lib/testing/storyboard/validations.js.map +1 -1
- package/dist/lib/testing/storyboard/validations.mjs +64 -24
- package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
- package/dist/lib/types/server-payload-aliases.d.mts +8 -2
- package/dist/lib/types/server-payload-aliases.d.ts +8 -2
- package/dist/lib/types/server-payload-aliases.d.ts.map +1 -1
- package/dist/lib/types/server-payload-aliases.js.map +1 -1
- package/dist/lib/upstream-recorder/recorder.d.mts +7 -18
- package/dist/lib/upstream-recorder/recorder.d.ts +7 -18
- package/dist/lib/upstream-recorder/recorder.d.ts.map +1 -1
- package/dist/lib/upstream-recorder/recorder.js +17 -10
- package/dist/lib/upstream-recorder/recorder.js.map +1 -1
- package/dist/lib/upstream-recorder/recorder.mjs +12 -5
- package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
- package/dist/lib/utils/redact-secrets.d.ts.map +1 -1
- package/dist/lib/utils/redact-secrets.js +7 -1
- package/dist/lib/utils/redact-secrets.js.map +1 -1
- package/dist/lib/utils/redact-secrets.mjs +7 -1
- package/dist/lib/utils/redact-secrets.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 -3
- package/dist/lib/version.mjs.map +1 -1
- package/docs/guides/BUILD-AN-AGENT.md +4 -2
- package/docs/llms.txt +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
import type { StoryboardContext } from './types.mjs';
|
|
2
2
|
export declare const BUILD_ASSETS_FROM_FORMAT_DIRECTIVE = "$build_assets_from_format";
|
|
3
|
+
type AssetsBuildFailure = {
|
|
4
|
+
reason: 'format_not_found' | 'malformed_directive';
|
|
5
|
+
constraint: string;
|
|
6
|
+
} | {
|
|
7
|
+
reason: 'fixture_unavailable';
|
|
8
|
+
slotId: string;
|
|
9
|
+
assetType: string;
|
|
10
|
+
constraint: string;
|
|
11
|
+
};
|
|
12
|
+
export type CreativeAssetExpansionFailure = AssetsBuildFailure & {
|
|
13
|
+
path: string;
|
|
14
|
+
};
|
|
15
|
+
export type CreativeAssetExpansionResult = {
|
|
16
|
+
ok: true;
|
|
17
|
+
value: unknown;
|
|
18
|
+
} | {
|
|
19
|
+
ok: false;
|
|
20
|
+
value: unknown;
|
|
21
|
+
failure: CreativeAssetExpansionFailure;
|
|
22
|
+
};
|
|
23
|
+
/** Expand reserved storyboard creative-asset directives and preserve the first failure diagnostic. */
|
|
24
|
+
export declare function expandCreativeAssetDirectivesWithDiagnostics(value: unknown, context: StoryboardContext, testKit: unknown): CreativeAssetExpansionResult;
|
|
3
25
|
/** Expand reserved storyboard creative-asset directives without mutating the fixture. */
|
|
4
26
|
export declare function expandCreativeAssetDirectives(value: unknown, context: StoryboardContext, testKit: unknown): unknown;
|
|
5
27
|
export declare function findUnresolvedCreativeAssetDirectives(value: unknown): string[];
|
|
28
|
+
export {};
|
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
import type { StoryboardContext } from './types';
|
|
2
2
|
export declare const BUILD_ASSETS_FROM_FORMAT_DIRECTIVE = "$build_assets_from_format";
|
|
3
|
+
type AssetsBuildFailure = {
|
|
4
|
+
reason: 'format_not_found' | 'malformed_directive';
|
|
5
|
+
constraint: string;
|
|
6
|
+
} | {
|
|
7
|
+
reason: 'fixture_unavailable';
|
|
8
|
+
slotId: string;
|
|
9
|
+
assetType: string;
|
|
10
|
+
constraint: string;
|
|
11
|
+
};
|
|
12
|
+
export type CreativeAssetExpansionFailure = AssetsBuildFailure & {
|
|
13
|
+
path: string;
|
|
14
|
+
};
|
|
15
|
+
export type CreativeAssetExpansionResult = {
|
|
16
|
+
ok: true;
|
|
17
|
+
value: unknown;
|
|
18
|
+
} | {
|
|
19
|
+
ok: false;
|
|
20
|
+
value: unknown;
|
|
21
|
+
failure: CreativeAssetExpansionFailure;
|
|
22
|
+
};
|
|
23
|
+
/** Expand reserved storyboard creative-asset directives and preserve the first failure diagnostic. */
|
|
24
|
+
export declare function expandCreativeAssetDirectivesWithDiagnostics(value: unknown, context: StoryboardContext, testKit: unknown): CreativeAssetExpansionResult;
|
|
3
25
|
/** Expand reserved storyboard creative-asset directives without mutating the fixture. */
|
|
4
26
|
export declare function expandCreativeAssetDirectives(value: unknown, context: StoryboardContext, testKit: unknown): unknown;
|
|
5
27
|
export declare function findUnresolvedCreativeAssetDirectives(value: unknown): string[];
|
|
28
|
+
export {};
|
|
6
29
|
//# sourceMappingURL=creative-assets.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"creative-assets.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/creative-assets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,eAAO,MAAM,kCAAkC,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"creative-assets.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/creative-assets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,eAAO,MAAM,kCAAkC,8BAA8B,CAAC;AAe9E,KAAK,kBAAkB,GACnB;IACE,MAAM,EAAE,kBAAkB,GAAG,qBAAqB,CAAC;IACnD,UAAU,EAAE,MAAM,CAAC;CACpB,GACD;IACE,MAAM,EAAE,qBAAqB,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEN,MAAM,MAAM,6BAA6B,GAAG,kBAAkB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAElF,MAAM,MAAM,4BAA4B,GACpC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC5B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,6BAA6B,CAAA;CAAE,CAAC;AA4d1E,sGAAsG;AACtG,wBAAgB,4CAA4C,CAC1D,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,OAAO,GACf,4BAA4B,CAE9B;AAED,yFAAyF;AACzF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAEnH;AAED,wBAAgB,qCAAqC,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAe9E"}
|
|
@@ -20,6 +20,7 @@ var creative_assets_exports = {};
|
|
|
20
20
|
__export(creative_assets_exports, {
|
|
21
21
|
BUILD_ASSETS_FROM_FORMAT_DIRECTIVE: () => BUILD_ASSETS_FROM_FORMAT_DIRECTIVE,
|
|
22
22
|
expandCreativeAssetDirectives: () => expandCreativeAssetDirectives,
|
|
23
|
+
expandCreativeAssetDirectivesWithDiagnostics: () => expandCreativeAssetDirectivesWithDiagnostics,
|
|
23
24
|
findUnresolvedCreativeAssetDirectives: () => findUnresolvedCreativeAssetDirectives
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(creative_assets_exports);
|
|
@@ -42,15 +43,41 @@ function formatIdMatches(candidate, requested) {
|
|
|
42
43
|
return requestedAgent === void 0 || candidateAgent === requestedAgent;
|
|
43
44
|
}
|
|
44
45
|
function resolveFormat(value, context) {
|
|
45
|
-
if (!isObject(value))
|
|
46
|
+
if (!isObject(value)) {
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
reason: "malformed_directive",
|
|
50
|
+
constraint: "directive value must be a format object or FormatId"
|
|
51
|
+
};
|
|
52
|
+
}
|
|
46
53
|
if (Array.isArray(value.slots) || Array.isArray(value.assets) || Array.isArray(value.assets_required)) {
|
|
47
|
-
return value;
|
|
54
|
+
return { ok: true, format: value };
|
|
55
|
+
}
|
|
56
|
+
if (typeof value.id !== "string") {
|
|
57
|
+
return { ok: false, reason: "malformed_directive", constraint: "format reference must contain a string id" };
|
|
48
58
|
}
|
|
49
|
-
if (typeof value.id !== "string") return void 0;
|
|
50
59
|
const formats = Array.isArray(context.formats) ? context.formats : [];
|
|
51
|
-
|
|
60
|
+
const format = formats.find(
|
|
52
61
|
(candidate) => isObject(candidate) && formatIdMatches(candidate.format_id, value)
|
|
53
62
|
);
|
|
63
|
+
if (!format) {
|
|
64
|
+
const agent = typeof value.agent_url === "string" ? ` from ${value.agent_url}` : "";
|
|
65
|
+
return {
|
|
66
|
+
ok: false,
|
|
67
|
+
reason: "format_not_found",
|
|
68
|
+
constraint: `format "${value.id}"${agent} is absent from storyboard context.formats`
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const catalogFormatId = isObject(format.format_id) ? format.format_id : {};
|
|
72
|
+
return {
|
|
73
|
+
ok: true,
|
|
74
|
+
format: {
|
|
75
|
+
...format,
|
|
76
|
+
...asNumber(value.width) !== void 0 ? { width: value.width } : {},
|
|
77
|
+
...asNumber(value.height) !== void 0 ? { height: value.height } : {},
|
|
78
|
+
format_id: { ...catalogFormatId, ...value }
|
|
79
|
+
}
|
|
80
|
+
};
|
|
54
81
|
}
|
|
55
82
|
function dimensionsFromId(format) {
|
|
56
83
|
const formatId = isObject(format.format_id) ? format.format_id.id : void 0;
|
|
@@ -58,7 +85,11 @@ function dimensionsFromId(format) {
|
|
|
58
85
|
return match ? { width: Number(match[1]), height: Number(match[2]) } : {};
|
|
59
86
|
}
|
|
60
87
|
function formatDimensions(format) {
|
|
61
|
-
const
|
|
88
|
+
const nestedFormatId = isObject(format.format_id) ? format.format_id : {};
|
|
89
|
+
const direct = {
|
|
90
|
+
width: asNumber(format.width) ?? asNumber(nestedFormatId.width),
|
|
91
|
+
height: asNumber(format.height) ?? asNumber(nestedFormatId.height)
|
|
92
|
+
};
|
|
62
93
|
if (direct.width !== void 0 || direct.height !== void 0) return direct;
|
|
63
94
|
const renders = Array.isArray(format.renders) ? format.renders : [];
|
|
64
95
|
for (const render of renders) {
|
|
@@ -81,79 +112,324 @@ function slotDimensions(slot, fallback) {
|
|
|
81
112
|
function requiredSlots(format) {
|
|
82
113
|
const canonicalSlots = Array.isArray(format.slots) ? format.slots : void 0;
|
|
83
114
|
const legacySlots = Array.isArray(format.assets) ? format.assets : Array.isArray(format.assets_required) ? format.assets_required : void 0;
|
|
115
|
+
const usesAssetsRequired = canonicalSlots === void 0 && !Array.isArray(format.assets) && legacySlots !== void 0;
|
|
84
116
|
const slots = canonicalSlots ?? legacySlots ?? [];
|
|
85
117
|
const fallback = formatDimensions(format);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
118
|
+
const container = canonicalSlots !== void 0 ? "slots" : usesAssetsRequired ? "assets_required" : "assets";
|
|
119
|
+
const required = [];
|
|
120
|
+
for (let index = 0; index < slots.length; index += 1) {
|
|
121
|
+
const slotValue = slots[index];
|
|
122
|
+
if (!isObject(slotValue) || !usesAssetsRequired && slotValue.required !== true) continue;
|
|
123
|
+
const isRepeatableGroup = slotValue.item_type === "repeatable_group";
|
|
124
|
+
const id = canonicalSlots !== void 0 || isRepeatableGroup ? slotValue.asset_group_id : slotValue.asset_id;
|
|
125
|
+
const assetType = typeof slotValue.asset_type === "string" ? slotValue.asset_type : isRepeatableGroup ? "repeatable_group" : void 0;
|
|
126
|
+
const idField = canonicalSlots !== void 0 || isRepeatableGroup ? "asset_group_id" : "asset_id";
|
|
127
|
+
if (typeof id !== "string") {
|
|
128
|
+
return { ok: false, constraint: `required ${container}[${index}].${idField} must be a string` };
|
|
129
|
+
}
|
|
130
|
+
if (assetType === void 0) {
|
|
131
|
+
return { ok: false, constraint: `required ${container}[${index}].asset_type must be a string` };
|
|
132
|
+
}
|
|
133
|
+
const requirements = isObject(slotValue.requirements) ? slotValue.requirements : {};
|
|
134
|
+
const dimensions = slotDimensions(slotValue, fallback);
|
|
135
|
+
required.push({ id, assetType, requirements, ...dimensions });
|
|
136
|
+
}
|
|
137
|
+
return { ok: true, slots: required };
|
|
138
|
+
}
|
|
139
|
+
function imageConstraint(slot) {
|
|
140
|
+
if (slot.width !== void 0 && slot.height !== void 0) {
|
|
141
|
+
return `requires an exact ${slot.width}x${slot.height} image fixture`;
|
|
142
|
+
}
|
|
143
|
+
if (slot.width !== void 0) return `requires an image fixture with exact width ${slot.width}`;
|
|
144
|
+
if (slot.height !== void 0) return `requires an image fixture with exact height ${slot.height}`;
|
|
145
|
+
return "requires an image fixture with a URL";
|
|
146
|
+
}
|
|
147
|
+
function imageFixtureMismatch(candidate, slot) {
|
|
148
|
+
const requirements = slot.requirements;
|
|
149
|
+
const supported = /* @__PURE__ */ new Set([
|
|
150
|
+
"width",
|
|
151
|
+
"height",
|
|
152
|
+
"dimensions",
|
|
153
|
+
"min_width",
|
|
154
|
+
"max_width",
|
|
155
|
+
"min_height",
|
|
156
|
+
"max_height",
|
|
157
|
+
"aspect_ratio",
|
|
158
|
+
"formats",
|
|
159
|
+
"pixel_ratios",
|
|
160
|
+
"parameters_from_format_id",
|
|
161
|
+
"unit"
|
|
162
|
+
]);
|
|
163
|
+
const unsupported = Object.keys(requirements).find((key) => !supported.has(key));
|
|
164
|
+
if (unsupported) return `cannot verify image requirement "${unsupported}" from fixture metadata`;
|
|
165
|
+
const unit = typeof requirements.unit === "string" ? requirements.unit : "px";
|
|
166
|
+
if (unit !== "px" && unit !== "pixel" && unit !== "pixels") {
|
|
167
|
+
return `requires image dimensions in unsupported unit "${unit}"`;
|
|
168
|
+
}
|
|
169
|
+
const width = asNumber(candidate.width);
|
|
170
|
+
const height = asNumber(candidate.height);
|
|
171
|
+
const minWidth = asNumber(requirements.min_width);
|
|
172
|
+
const maxWidth = asNumber(requirements.max_width);
|
|
173
|
+
const minHeight = asNumber(requirements.min_height);
|
|
174
|
+
const maxHeight = asNumber(requirements.max_height);
|
|
175
|
+
if (minWidth !== void 0 && (width === void 0 || width < minWidth)) return `requires minimum width ${minWidth}`;
|
|
176
|
+
if (maxWidth !== void 0 && (width === void 0 || width > maxWidth)) return `requires maximum width ${maxWidth}`;
|
|
177
|
+
if (minHeight !== void 0 && (height === void 0 || height < minHeight)) {
|
|
178
|
+
return `requires minimum height ${minHeight}`;
|
|
179
|
+
}
|
|
180
|
+
if (maxHeight !== void 0 && (height === void 0 || height > maxHeight)) {
|
|
181
|
+
return `requires maximum height ${maxHeight}`;
|
|
182
|
+
}
|
|
183
|
+
if (typeof requirements.aspect_ratio === "string") {
|
|
184
|
+
const match = /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?)$/.exec(requirements.aspect_ratio);
|
|
185
|
+
if (!match || width === void 0 || height === void 0) {
|
|
186
|
+
return `cannot verify aspect ratio "${requirements.aspect_ratio}"`;
|
|
187
|
+
}
|
|
188
|
+
const expected = Number(match[1]) / Number(match[2]);
|
|
189
|
+
if (Math.abs(width / height - expected) > 1e-3) return `requires aspect ratio ${requirements.aspect_ratio}`;
|
|
190
|
+
}
|
|
191
|
+
if (Array.isArray(requirements.formats)) {
|
|
192
|
+
const mimeType = typeof candidate.mime_type === "string" ? candidate.mime_type.toLowerCase() : "";
|
|
193
|
+
const extension = mimeType.split("/")[1]?.replace("jpeg", "jpg");
|
|
194
|
+
const allowed = requirements.formats.filter((item) => typeof item === "string").map((item) => item.toLowerCase().replace("jpeg", "jpg"));
|
|
195
|
+
if (!extension || !allowed.includes(extension)) return `requires image format in [${allowed.join(", ")}]`;
|
|
196
|
+
}
|
|
197
|
+
if (Array.isArray(requirements.pixel_ratios)) {
|
|
198
|
+
const ratio = asNumber(candidate.pixel_ratio) ?? 1;
|
|
199
|
+
const allowed = requirements.pixel_ratios.filter((item) => asNumber(item) !== void 0);
|
|
200
|
+
if (!allowed.includes(ratio)) return `requires pixel ratio in [${allowed.join(", ")}]`;
|
|
201
|
+
}
|
|
202
|
+
return void 0;
|
|
92
203
|
}
|
|
93
204
|
function buildImage(slot, assets) {
|
|
94
205
|
const images = Array.isArray(assets.images) ? assets.images.filter(isObject) : [];
|
|
206
|
+
let mismatch;
|
|
95
207
|
const image = images.find((candidate) => {
|
|
96
208
|
const widthMatches = slot.width === void 0 || candidate.width === slot.width;
|
|
97
209
|
const heightMatches = slot.height === void 0 || candidate.height === slot.height;
|
|
98
|
-
|
|
210
|
+
if (!widthMatches || !heightMatches) return false;
|
|
211
|
+
const candidateMismatch = imageFixtureMismatch(candidate, slot);
|
|
212
|
+
if (candidateMismatch) {
|
|
213
|
+
mismatch ??= candidateMismatch;
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
return true;
|
|
99
217
|
});
|
|
100
|
-
if (!image
|
|
218
|
+
if (!image) {
|
|
219
|
+
return { ok: false, constraint: mismatch ? `${imageConstraint(slot)}; ${mismatch}` : imageConstraint(slot) };
|
|
220
|
+
}
|
|
221
|
+
if (typeof image.url !== "string") {
|
|
222
|
+
return { ok: false, constraint: `${imageConstraint(slot)}, but the matching fixture has no URL` };
|
|
223
|
+
}
|
|
101
224
|
return {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
225
|
+
ok: true,
|
|
226
|
+
asset: {
|
|
227
|
+
asset_type: "image",
|
|
228
|
+
url: image.url,
|
|
229
|
+
...asNumber(image.width) !== void 0 ? { width: image.width } : {},
|
|
230
|
+
...asNumber(image.height) !== void 0 ? { height: image.height } : {},
|
|
231
|
+
...typeof image.mime_type === "string" ? { mime_type: image.mime_type } : {}
|
|
232
|
+
}
|
|
107
233
|
};
|
|
108
234
|
}
|
|
109
|
-
function
|
|
110
|
-
|
|
235
|
+
function textFixtureMismatch(content, requirements) {
|
|
236
|
+
const supported = /* @__PURE__ */ new Set([
|
|
237
|
+
"min_length",
|
|
238
|
+
"max_length",
|
|
239
|
+
"min_lines",
|
|
240
|
+
"max_lines",
|
|
241
|
+
"prohibited_terms",
|
|
242
|
+
"allowed_values"
|
|
243
|
+
]);
|
|
244
|
+
const unsupported = Object.keys(requirements).find((key) => !supported.has(key));
|
|
245
|
+
if (unsupported) return `cannot verify text requirement "${unsupported}"`;
|
|
246
|
+
const minLength = asNumber(requirements.min_length);
|
|
247
|
+
const maxLength = asNumber(requirements.max_length);
|
|
248
|
+
if (minLength !== void 0 && content.length < minLength) return `requires minimum length ${minLength}`;
|
|
249
|
+
if (maxLength !== void 0 && content.length > maxLength) return `requires maximum length ${maxLength}`;
|
|
250
|
+
const lines = content.split(/\r?\n/).length;
|
|
251
|
+
const minLines = asNumber(requirements.min_lines);
|
|
252
|
+
const maxLines = asNumber(requirements.max_lines);
|
|
253
|
+
if (minLines !== void 0 && lines < minLines) return `requires minimum line count ${minLines}`;
|
|
254
|
+
if (maxLines !== void 0 && lines > maxLines) return `requires maximum line count ${maxLines}`;
|
|
255
|
+
if (Array.isArray(requirements.prohibited_terms)) {
|
|
256
|
+
const prohibited = requirements.prohibited_terms.find(
|
|
257
|
+
(term) => typeof term === "string" && content.toLowerCase().includes(term.toLowerCase())
|
|
258
|
+
);
|
|
259
|
+
if (prohibited) return `prohibits term "${prohibited}"`;
|
|
260
|
+
}
|
|
261
|
+
if (Array.isArray(requirements.allowed_values) && !requirements.allowed_values.some((value) => typeof value === "string" && value === content)) {
|
|
262
|
+
return "requires one of the declared allowed_values";
|
|
263
|
+
}
|
|
264
|
+
return void 0;
|
|
111
265
|
}
|
|
112
266
|
function buildText(slot, assets) {
|
|
113
267
|
const text = isObject(assets.text) ? assets.text : {};
|
|
114
268
|
const id = slot.id.toLowerCase();
|
|
115
|
-
const
|
|
116
|
-
|
|
269
|
+
const fixtureCategory = {
|
|
270
|
+
headline: "headlines",
|
|
271
|
+
title: "headlines",
|
|
272
|
+
description: "descriptions",
|
|
273
|
+
body: "descriptions",
|
|
274
|
+
body_text: "descriptions",
|
|
275
|
+
primary_text: "descriptions",
|
|
276
|
+
cta: "cta",
|
|
277
|
+
cta_text: "cta",
|
|
278
|
+
call_to_action: "cta"
|
|
279
|
+
}[id];
|
|
280
|
+
if (fixtureCategory === void 0) {
|
|
281
|
+
return {
|
|
282
|
+
ok: false,
|
|
283
|
+
constraint: "slot id has no exact runner mapping to a headlines, descriptions, or CTA fixture category"
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
const candidates = Array.isArray(text[fixtureCategory]) ? text[fixtureCategory].filter((item) => typeof item === "string") : [];
|
|
287
|
+
let mismatch;
|
|
288
|
+
const content = candidates.find((candidate) => {
|
|
289
|
+
const candidateMismatch = textFixtureMismatch(candidate, slot.requirements);
|
|
290
|
+
if (candidateMismatch) {
|
|
291
|
+
mismatch ??= candidateMismatch;
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
return true;
|
|
295
|
+
});
|
|
296
|
+
return content === void 0 ? {
|
|
297
|
+
ok: false,
|
|
298
|
+
constraint: mismatch ?? `requires a ${fixtureCategory} text fixture`
|
|
299
|
+
} : { ok: true, asset: { asset_type: "text", content } };
|
|
300
|
+
}
|
|
301
|
+
function containsUrlMacro(value) {
|
|
302
|
+
let inMacro = false;
|
|
303
|
+
let hasContent = false;
|
|
304
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
305
|
+
if (!inMacro) {
|
|
306
|
+
if (value[index] === "$" && value[index + 1] === "{") {
|
|
307
|
+
inMacro = true;
|
|
308
|
+
hasContent = false;
|
|
309
|
+
index += 1;
|
|
310
|
+
}
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
if (value[index] === "}") {
|
|
314
|
+
if (hasContent) return true;
|
|
315
|
+
inMacro = false;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
hasContent = true;
|
|
319
|
+
}
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
function buildUrl(slot, assets) {
|
|
323
|
+
if (typeof assets.click_url !== "string") return { ok: false, constraint: "requires a click_url fixture" };
|
|
324
|
+
const url = assets.click_url;
|
|
325
|
+
const supported = /* @__PURE__ */ new Set(["role", "protocols", "allowed_domains", "max_length", "macro_support"]);
|
|
326
|
+
const unsupported = Object.keys(slot.requirements).find((key) => !supported.has(key));
|
|
327
|
+
if (unsupported) return { ok: false, constraint: `cannot verify URL requirement "${unsupported}"` };
|
|
328
|
+
const maxLength = asNumber(slot.requirements.max_length);
|
|
329
|
+
if (maxLength !== void 0 && url.length > maxLength) {
|
|
330
|
+
return { ok: false, constraint: `requires URL maximum length ${maxLength}` };
|
|
331
|
+
}
|
|
332
|
+
let parsed;
|
|
333
|
+
try {
|
|
334
|
+
parsed = new URL(url);
|
|
335
|
+
} catch {
|
|
336
|
+
return { ok: false, constraint: "click_url fixture is not an absolute URL" };
|
|
337
|
+
}
|
|
338
|
+
if (Array.isArray(slot.requirements.protocols) && !slot.requirements.protocols.some((protocol) => protocol === parsed.protocol.replace(/:$/, ""))) {
|
|
339
|
+
return { ok: false, constraint: "click_url fixture uses a disallowed protocol" };
|
|
340
|
+
}
|
|
341
|
+
if (Array.isArray(slot.requirements.allowed_domains) && !slot.requirements.allowed_domains.some((domain) => domain === parsed.hostname)) {
|
|
342
|
+
return { ok: false, constraint: "click_url fixture uses a disallowed domain" };
|
|
343
|
+
}
|
|
344
|
+
if (slot.requirements.macro_support === true && !containsUrlMacro(url)) {
|
|
345
|
+
return { ok: false, constraint: "requires a URL fixture with macro support" };
|
|
346
|
+
}
|
|
347
|
+
return { ok: true, asset: { asset_type: "url", url } };
|
|
117
348
|
}
|
|
118
349
|
function buildAsset(slot, testKit) {
|
|
119
|
-
if (!isObject(testKit) || !isObject(testKit.assets))
|
|
350
|
+
if (!isObject(testKit) || !isObject(testKit.assets)) {
|
|
351
|
+
return { ok: false, constraint: "selected test kit does not declare asset fixtures" };
|
|
352
|
+
}
|
|
120
353
|
const assets = testKit.assets;
|
|
121
354
|
if (slot.assetType === "image") return buildImage(slot, assets);
|
|
122
|
-
if (slot.assetType === "url"
|
|
123
|
-
return { asset_type: "url", url: assets.click_url };
|
|
124
|
-
}
|
|
355
|
+
if (slot.assetType === "url") return buildUrl(slot, assets);
|
|
125
356
|
if (slot.assetType === "text") return buildText(slot, assets);
|
|
126
|
-
return
|
|
357
|
+
return { ok: false, constraint: `asset type "${slot.assetType}" is not supported by the selected test kit` };
|
|
127
358
|
}
|
|
128
359
|
function buildAssets(value, context, testKit) {
|
|
129
|
-
const
|
|
130
|
-
if (!
|
|
131
|
-
|
|
132
|
-
|
|
360
|
+
const resolved = resolveFormat(value, context);
|
|
361
|
+
if (!resolved.ok) {
|
|
362
|
+
return { ok: false, failure: { reason: resolved.reason, constraint: resolved.constraint } };
|
|
363
|
+
}
|
|
364
|
+
const required = requiredSlots(resolved.format);
|
|
365
|
+
if (!required.ok) {
|
|
366
|
+
return { ok: false, failure: { reason: "malformed_directive", constraint: required.constraint } };
|
|
367
|
+
}
|
|
133
368
|
const built = {};
|
|
134
|
-
for (const slot of slots) {
|
|
135
|
-
const
|
|
136
|
-
if (!
|
|
137
|
-
|
|
369
|
+
for (const slot of required.slots) {
|
|
370
|
+
const result = buildAsset(slot, testKit);
|
|
371
|
+
if (!result.ok) {
|
|
372
|
+
return {
|
|
373
|
+
ok: false,
|
|
374
|
+
failure: {
|
|
375
|
+
reason: "fixture_unavailable",
|
|
376
|
+
slotId: slot.id,
|
|
377
|
+
assetType: slot.assetType,
|
|
378
|
+
constraint: result.constraint
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
built[slot.id] = result.asset;
|
|
138
383
|
}
|
|
139
|
-
return built;
|
|
384
|
+
return { ok: true, assets: built };
|
|
140
385
|
}
|
|
141
|
-
function
|
|
386
|
+
function expandWithDiagnostics(value, context, testKit, path) {
|
|
142
387
|
if (Array.isArray(value)) {
|
|
143
|
-
|
|
388
|
+
const expanded2 = Array.from(value);
|
|
389
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
390
|
+
const result = expandWithDiagnostics(value[index], context, testKit, `${path}[${index}]`);
|
|
391
|
+
expanded2[index] = result.value;
|
|
392
|
+
if (!result.ok) return { ...result, value: expanded2 };
|
|
393
|
+
}
|
|
394
|
+
return { ok: true, value: expanded2 };
|
|
144
395
|
}
|
|
145
|
-
if (!isObject(value)) return value;
|
|
396
|
+
if (!isObject(value)) return { ok: true, value };
|
|
146
397
|
if (Object.prototype.hasOwnProperty.call(value, BUILD_ASSETS_FROM_FORMAT_DIRECTIVE)) {
|
|
147
398
|
const built = buildAssets(value[BUILD_ASSETS_FROM_FORMAT_DIRECTIVE], context, testKit);
|
|
148
|
-
if (!built)
|
|
399
|
+
if (!built.ok) {
|
|
400
|
+
return {
|
|
401
|
+
ok: false,
|
|
402
|
+
value,
|
|
403
|
+
failure: {
|
|
404
|
+
...built.failure,
|
|
405
|
+
path: `${path}.${BUILD_ASSETS_FROM_FORMAT_DIRECTIVE}`
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
}
|
|
149
409
|
const siblings = Object.fromEntries(
|
|
150
|
-
Object.entries(value).filter(([key]) => key !== BUILD_ASSETS_FROM_FORMAT_DIRECTIVE)
|
|
410
|
+
Object.entries(value).filter(([key]) => key !== BUILD_ASSETS_FROM_FORMAT_DIRECTIVE)
|
|
151
411
|
);
|
|
152
|
-
|
|
412
|
+
for (const [key, item] of Object.entries(value)) {
|
|
413
|
+
if (key === BUILD_ASSETS_FROM_FORMAT_DIRECTIVE) continue;
|
|
414
|
+
const result = expandWithDiagnostics(item, context, testKit, `${path}.${key}`);
|
|
415
|
+
siblings[key] = result.value;
|
|
416
|
+
if (!result.ok) return { ...result, value: { ...siblings, ...built.assets } };
|
|
417
|
+
}
|
|
418
|
+
return { ok: true, value: { ...siblings, ...built.assets } };
|
|
153
419
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
420
|
+
const expanded = { ...value };
|
|
421
|
+
for (const [key, item] of Object.entries(value)) {
|
|
422
|
+
const result = expandWithDiagnostics(item, context, testKit, `${path}.${key}`);
|
|
423
|
+
expanded[key] = result.value;
|
|
424
|
+
if (!result.ok) return { ...result, value: expanded };
|
|
425
|
+
}
|
|
426
|
+
return { ok: true, value: expanded };
|
|
427
|
+
}
|
|
428
|
+
function expandCreativeAssetDirectivesWithDiagnostics(value, context, testKit) {
|
|
429
|
+
return expandWithDiagnostics(value, context, testKit, "$");
|
|
430
|
+
}
|
|
431
|
+
function expandCreativeAssetDirectives(value, context, testKit) {
|
|
432
|
+
return expandCreativeAssetDirectivesWithDiagnostics(value, context, testKit).value;
|
|
157
433
|
}
|
|
158
434
|
function findUnresolvedCreativeAssetDirectives(value) {
|
|
159
435
|
const paths = [];
|
|
@@ -175,6 +451,7 @@ function findUnresolvedCreativeAssetDirectives(value) {
|
|
|
175
451
|
0 && (module.exports = {
|
|
176
452
|
BUILD_ASSETS_FROM_FORMAT_DIRECTIVE,
|
|
177
453
|
expandCreativeAssetDirectives,
|
|
454
|
+
expandCreativeAssetDirectivesWithDiagnostics,
|
|
178
455
|
findUnresolvedCreativeAssetDirectives
|
|
179
456
|
});
|
|
180
457
|
//# sourceMappingURL=creative-assets.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/storyboard/creative-assets.ts"],"sourcesContent":["import type { StoryboardContext } from './types';\n\nexport const BUILD_ASSETS_FROM_FORMAT_DIRECTIVE = '$build_assets_from_format';\n\ntype JsonObject = Record<string, unknown>;\n\ninterface Dimensions {\n width?: number;\n height?: number;\n}\n\ninterface RequiredSlot extends Dimensions {\n id: string;\n assetType: string;\n}\n\nfunction isObject(value: unknown): value is JsonObject {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction normalizeAgentUrl(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n return value.replace(/\\/$/, '');\n}\n\nfunction formatIdMatches(candidate: unknown, requested: JsonObject): boolean {\n if (!isObject(candidate)) return false;\n if (candidate.id !== requested.id) return false;\n const requestedAgent = normalizeAgentUrl(requested.agent_url);\n const candidateAgent = normalizeAgentUrl(candidate.agent_url);\n return requestedAgent === undefined || candidateAgent === requestedAgent;\n}\n\nfunction resolveFormat(value: unknown, context: StoryboardContext): JsonObject | undefined {\n if (!isObject(value)) return undefined;\n if (Array.isArray(value.slots) || Array.isArray(value.assets) || Array.isArray(value.assets_required)) {\n return value;\n }\n\n if (typeof value.id !== 'string') return undefined;\n const formats = Array.isArray(context.formats) ? context.formats : [];\n return formats.find(\n (candidate): candidate is JsonObject => isObject(candidate) && formatIdMatches(candidate.format_id, value)\n );\n}\n\nfunction dimensionsFromId(format: JsonObject): Dimensions {\n const formatId = isObject(format.format_id) ? format.format_id.id : undefined;\n const match = typeof formatId === 'string' ? formatId.match(/(?:^|_)(\\d{2,4})x(\\d{2,4})(?:_|$)/i) : null;\n return match ? { width: Number(match[1]), height: Number(match[2]) } : {};\n}\n\nfunction formatDimensions(format: JsonObject): Dimensions {\n const direct = { width: asNumber(format.width), height: asNumber(format.height) };\n if (direct.width !== undefined || direct.height !== undefined) return direct;\n\n const renders = Array.isArray(format.renders) ? format.renders : [];\n for (const render of renders) {\n if (!isObject(render)) continue;\n const dimensions = isObject(render.dimensions) ? render.dimensions : render;\n const width = asNumber(dimensions.width);\n const height = asNumber(dimensions.height);\n if (width !== undefined || height !== undefined) return { width, height };\n }\n\n return dimensionsFromId(format);\n}\n\nfunction slotDimensions(slot: JsonObject, fallback: Dimensions): Dimensions {\n const requirements = isObject(slot.requirements) ? slot.requirements : {};\n const nested = isObject(requirements.dimensions) ? requirements.dimensions : requirements;\n return {\n width: asNumber(slot.width) ?? asNumber(nested.width) ?? fallback.width,\n height: asNumber(slot.height) ?? asNumber(nested.height) ?? fallback.height,\n };\n}\n\nfunction requiredSlots(format: JsonObject): RequiredSlot[] {\n const canonicalSlots = Array.isArray(format.slots) ? format.slots : undefined;\n const legacySlots = Array.isArray(format.assets)\n ? format.assets\n : Array.isArray(format.assets_required)\n ? format.assets_required\n : undefined;\n const slots = canonicalSlots ?? legacySlots ?? [];\n const fallback = formatDimensions(format);\n\n return slots.flatMap(slotValue => {\n if (!isObject(slotValue) || slotValue.required !== true) return [];\n const id = canonicalSlots ? slotValue.asset_group_id : slotValue.asset_id;\n if (typeof id !== 'string' || typeof slotValue.asset_type !== 'string') return [];\n return [{ id, assetType: slotValue.asset_type, ...slotDimensions(slotValue, fallback) }];\n });\n}\n\nfunction buildImage(slot: RequiredSlot, assets: JsonObject): JsonObject | undefined {\n const images = Array.isArray(assets.images) ? assets.images.filter(isObject) : [];\n const image = images.find(candidate => {\n const widthMatches = slot.width === undefined || candidate.width === slot.width;\n const heightMatches = slot.height === undefined || candidate.height === slot.height;\n return widthMatches && heightMatches;\n });\n if (!image || typeof image.url !== 'string') return undefined;\n return {\n asset_type: 'image',\n url: image.url,\n ...(asNumber(image.width) !== undefined ? { width: image.width } : {}),\n ...(asNumber(image.height) !== undefined ? { height: image.height } : {}),\n ...(typeof image.mime_type === 'string' ? { mime_type: image.mime_type } : {}),\n };\n}\n\nfunction firstString(value: unknown): string | undefined {\n return Array.isArray(value) ? value.find((item): item is string => typeof item === 'string') : undefined;\n}\n\nfunction buildText(slot: RequiredSlot, assets: JsonObject): JsonObject | undefined {\n const text = isObject(assets.text) ? assets.text : {};\n const id = slot.id.toLowerCase();\n const content = id.includes('headline')\n ? firstString(text.headlines)\n : id.includes('description') || id.includes('body')\n ? firstString(text.descriptions)\n : id.includes('cta') || id.includes('call_to_action')\n ? firstString(text.cta)\n : (firstString(text.headlines) ?? firstString(text.descriptions) ?? firstString(text.cta));\n return content === undefined ? undefined : { asset_type: 'text', content };\n}\n\nfunction buildAsset(slot: RequiredSlot, testKit: unknown): JsonObject | undefined {\n if (!isObject(testKit) || !isObject(testKit.assets)) return undefined;\n const assets = testKit.assets;\n if (slot.assetType === 'image') return buildImage(slot, assets);\n if (slot.assetType === 'url' && typeof assets.click_url === 'string') {\n return { asset_type: 'url', url: assets.click_url };\n }\n if (slot.assetType === 'text') return buildText(slot, assets);\n return undefined;\n}\n\nfunction buildAssets(value: unknown, context: StoryboardContext, testKit: unknown): JsonObject | undefined {\n const format = resolveFormat(value, context);\n if (!format) return undefined;\n const slots = requiredSlots(format);\n if (slots.length === 0) return undefined;\n\n const built: JsonObject = {};\n for (const slot of slots) {\n const asset = buildAsset(slot, testKit);\n if (!asset) return undefined;\n built[slot.id] = asset;\n }\n return built;\n}\n\n/** Expand reserved storyboard creative-asset directives without mutating the fixture. */\nexport function expandCreativeAssetDirectives(value: unknown, context: StoryboardContext, testKit: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(item => expandCreativeAssetDirectives(item, context, testKit));\n }\n if (!isObject(value)) return value;\n\n if (Object.prototype.hasOwnProperty.call(value, BUILD_ASSETS_FROM_FORMAT_DIRECTIVE)) {\n const built = buildAssets(value[BUILD_ASSETS_FROM_FORMAT_DIRECTIVE], context, testKit);\n if (!built) return value;\n const siblings = Object.fromEntries(\n Object.entries(value)\n .filter(([key]) => key !== BUILD_ASSETS_FROM_FORMAT_DIRECTIVE)\n .map(([key, item]) => [key, expandCreativeAssetDirectives(item, context, testKit)])\n );\n return { ...siblings, ...built };\n }\n\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, expandCreativeAssetDirectives(item, context, testKit)])\n );\n}\n\nexport function findUnresolvedCreativeAssetDirectives(value: unknown): string[] {\n const paths: string[] = [];\n const walk = (item: unknown, path: string) => {\n if (Array.isArray(item)) {\n item.forEach((entry, index) => walk(entry, `${path}[${index}]`));\n return;\n }\n if (!isObject(item)) return;\n if (Object.prototype.hasOwnProperty.call(item, BUILD_ASSETS_FROM_FORMAT_DIRECTIVE)) {\n paths.push(`${path}.${BUILD_ASSETS_FROM_FORMAT_DIRECTIVE}`);\n }\n Object.entries(item).forEach(([key, entry]) => walk(entry, path ? `${path}.${key}` : key));\n };\n walk(value, '$');\n return paths;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/storyboard/creative-assets.ts"],"sourcesContent":["import type { StoryboardContext } from './types';\n\nexport const BUILD_ASSETS_FROM_FORMAT_DIRECTIVE = '$build_assets_from_format';\n\ntype JsonObject = Record<string, unknown>;\n\ninterface Dimensions {\n width?: number;\n height?: number;\n}\n\ninterface RequiredSlot extends Dimensions {\n id: string;\n assetType: string;\n requirements: JsonObject;\n}\n\ntype AssetsBuildFailure =\n | {\n reason: 'format_not_found' | 'malformed_directive';\n constraint: string;\n }\n | {\n reason: 'fixture_unavailable';\n slotId: string;\n assetType: string;\n constraint: string;\n };\n\nexport type CreativeAssetExpansionFailure = AssetsBuildFailure & { path: string };\n\nexport type CreativeAssetExpansionResult =\n | { ok: true; value: unknown }\n | { ok: false; value: unknown; failure: CreativeAssetExpansionFailure };\n\ntype AssetBuildResult = { ok: true; asset: JsonObject } | { ok: false; constraint: string };\n\ntype AssetsBuildResult = { ok: true; assets: JsonObject } | { ok: false; failure: AssetsBuildFailure };\n\ntype RequiredSlotsResult = { ok: true; slots: RequiredSlot[] } | { ok: false; constraint: string };\n\nfunction isObject(value: unknown): value is JsonObject {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction normalizeAgentUrl(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n return value.replace(/\\/$/, '');\n}\n\nfunction formatIdMatches(candidate: unknown, requested: JsonObject): boolean {\n if (!isObject(candidate)) return false;\n if (candidate.id !== requested.id) return false;\n const requestedAgent = normalizeAgentUrl(requested.agent_url);\n const candidateAgent = normalizeAgentUrl(candidate.agent_url);\n return requestedAgent === undefined || candidateAgent === requestedAgent;\n}\n\nfunction resolveFormat(\n value: unknown,\n context: StoryboardContext\n):\n | { ok: true; format: JsonObject }\n | { ok: false; reason: 'format_not_found' | 'malformed_directive'; constraint: string } {\n if (!isObject(value)) {\n return {\n ok: false,\n reason: 'malformed_directive',\n constraint: 'directive value must be a format object or FormatId',\n };\n }\n if (Array.isArray(value.slots) || Array.isArray(value.assets) || Array.isArray(value.assets_required)) {\n return { ok: true, format: value };\n }\n\n if (typeof value.id !== 'string') {\n return { ok: false, reason: 'malformed_directive', constraint: 'format reference must contain a string id' };\n }\n const formats = Array.isArray(context.formats) ? context.formats : [];\n const format = formats.find(\n (candidate): candidate is JsonObject => isObject(candidate) && formatIdMatches(candidate.format_id, value)\n );\n if (!format) {\n const agent = typeof value.agent_url === 'string' ? ` from ${value.agent_url}` : '';\n return {\n ok: false,\n reason: 'format_not_found',\n constraint: `format \"${value.id}\"${agent} is absent from storyboard context.formats`,\n };\n }\n const catalogFormatId = isObject(format.format_id) ? format.format_id : {};\n return {\n ok: true,\n format: {\n ...format,\n ...(asNumber(value.width) !== undefined ? { width: value.width } : {}),\n ...(asNumber(value.height) !== undefined ? { height: value.height } : {}),\n format_id: { ...catalogFormatId, ...value },\n },\n };\n}\n\nfunction dimensionsFromId(format: JsonObject): Dimensions {\n const formatId = isObject(format.format_id) ? format.format_id.id : undefined;\n const match = typeof formatId === 'string' ? formatId.match(/(?:^|_)(\\d{2,4})x(\\d{2,4})(?:_|$)/i) : null;\n return match ? { width: Number(match[1]), height: Number(match[2]) } : {};\n}\n\nfunction formatDimensions(format: JsonObject): Dimensions {\n const nestedFormatId = isObject(format.format_id) ? format.format_id : {};\n const direct = {\n width: asNumber(format.width) ?? asNumber(nestedFormatId.width),\n height: asNumber(format.height) ?? asNumber(nestedFormatId.height),\n };\n if (direct.width !== undefined || direct.height !== undefined) return direct;\n\n const renders = Array.isArray(format.renders) ? format.renders : [];\n for (const render of renders) {\n if (!isObject(render)) continue;\n const dimensions = isObject(render.dimensions) ? render.dimensions : render;\n const width = asNumber(dimensions.width);\n const height = asNumber(dimensions.height);\n if (width !== undefined || height !== undefined) return { width, height };\n }\n\n return dimensionsFromId(format);\n}\n\nfunction slotDimensions(slot: JsonObject, fallback: Dimensions): Dimensions {\n const requirements = isObject(slot.requirements) ? slot.requirements : {};\n const nested = isObject(requirements.dimensions) ? requirements.dimensions : requirements;\n return {\n width: asNumber(slot.width) ?? asNumber(nested.width) ?? fallback.width,\n height: asNumber(slot.height) ?? asNumber(nested.height) ?? fallback.height,\n };\n}\n\nfunction requiredSlots(format: JsonObject): RequiredSlotsResult {\n const canonicalSlots = Array.isArray(format.slots) ? format.slots : undefined;\n const legacySlots = Array.isArray(format.assets)\n ? format.assets\n : Array.isArray(format.assets_required)\n ? format.assets_required\n : undefined;\n const usesAssetsRequired = canonicalSlots === undefined && !Array.isArray(format.assets) && legacySlots !== undefined;\n const slots = canonicalSlots ?? legacySlots ?? [];\n const fallback = formatDimensions(format);\n const container = canonicalSlots !== undefined ? 'slots' : usesAssetsRequired ? 'assets_required' : 'assets';\n\n const required: RequiredSlot[] = [];\n for (let index = 0; index < slots.length; index += 1) {\n const slotValue = slots[index];\n if (!isObject(slotValue) || (!usesAssetsRequired && slotValue.required !== true)) continue;\n const isRepeatableGroup = slotValue.item_type === 'repeatable_group';\n const id = canonicalSlots !== undefined || isRepeatableGroup ? slotValue.asset_group_id : slotValue.asset_id;\n const assetType =\n typeof slotValue.asset_type === 'string'\n ? slotValue.asset_type\n : isRepeatableGroup\n ? 'repeatable_group'\n : undefined;\n const idField = canonicalSlots !== undefined || isRepeatableGroup ? 'asset_group_id' : 'asset_id';\n if (typeof id !== 'string') {\n return { ok: false, constraint: `required ${container}[${index}].${idField} must be a string` };\n }\n if (assetType === undefined) {\n return { ok: false, constraint: `required ${container}[${index}].asset_type must be a string` };\n }\n const requirements = isObject(slotValue.requirements) ? slotValue.requirements : {};\n const dimensions = slotDimensions(slotValue, fallback);\n required.push({ id, assetType, requirements, ...dimensions });\n }\n return { ok: true, slots: required };\n}\n\nfunction imageConstraint(slot: RequiredSlot): string {\n if (slot.width !== undefined && slot.height !== undefined) {\n return `requires an exact ${slot.width}x${slot.height} image fixture`;\n }\n if (slot.width !== undefined) return `requires an image fixture with exact width ${slot.width}`;\n if (slot.height !== undefined) return `requires an image fixture with exact height ${slot.height}`;\n return 'requires an image fixture with a URL';\n}\n\nfunction imageFixtureMismatch(candidate: JsonObject, slot: RequiredSlot): string | undefined {\n const requirements = slot.requirements;\n const supported = new Set([\n 'width',\n 'height',\n 'dimensions',\n 'min_width',\n 'max_width',\n 'min_height',\n 'max_height',\n 'aspect_ratio',\n 'formats',\n 'pixel_ratios',\n 'parameters_from_format_id',\n 'unit',\n ]);\n const unsupported = Object.keys(requirements).find(key => !supported.has(key));\n if (unsupported) return `cannot verify image requirement \"${unsupported}\" from fixture metadata`;\n\n const unit = typeof requirements.unit === 'string' ? requirements.unit : 'px';\n if (unit !== 'px' && unit !== 'pixel' && unit !== 'pixels') {\n return `requires image dimensions in unsupported unit \"${unit}\"`;\n }\n\n const width = asNumber(candidate.width);\n const height = asNumber(candidate.height);\n const minWidth = asNumber(requirements.min_width);\n const maxWidth = asNumber(requirements.max_width);\n const minHeight = asNumber(requirements.min_height);\n const maxHeight = asNumber(requirements.max_height);\n if (minWidth !== undefined && (width === undefined || width < minWidth)) return `requires minimum width ${minWidth}`;\n if (maxWidth !== undefined && (width === undefined || width > maxWidth)) return `requires maximum width ${maxWidth}`;\n if (minHeight !== undefined && (height === undefined || height < minHeight)) {\n return `requires minimum height ${minHeight}`;\n }\n if (maxHeight !== undefined && (height === undefined || height > maxHeight)) {\n return `requires maximum height ${maxHeight}`;\n }\n\n if (typeof requirements.aspect_ratio === 'string') {\n const match = /^(\\d+(?:\\.\\d+)?):(\\d+(?:\\.\\d+)?)$/.exec(requirements.aspect_ratio);\n if (!match || width === undefined || height === undefined) {\n return `cannot verify aspect ratio \"${requirements.aspect_ratio}\"`;\n }\n const expected = Number(match[1]) / Number(match[2]);\n if (Math.abs(width / height - expected) > 0.001) return `requires aspect ratio ${requirements.aspect_ratio}`;\n }\n\n if (Array.isArray(requirements.formats)) {\n const mimeType = typeof candidate.mime_type === 'string' ? candidate.mime_type.toLowerCase() : '';\n const extension = mimeType.split('/')[1]?.replace('jpeg', 'jpg');\n const allowed = requirements.formats\n .filter((item): item is string => typeof item === 'string')\n .map(item => item.toLowerCase().replace('jpeg', 'jpg'));\n if (!extension || !allowed.includes(extension)) return `requires image format in [${allowed.join(', ')}]`;\n }\n\n if (Array.isArray(requirements.pixel_ratios)) {\n const ratio = asNumber(candidate.pixel_ratio) ?? 1;\n const allowed = requirements.pixel_ratios.filter((item): item is number => asNumber(item) !== undefined);\n if (!allowed.includes(ratio)) return `requires pixel ratio in [${allowed.join(', ')}]`;\n }\n return undefined;\n}\n\nfunction buildImage(slot: RequiredSlot, assets: JsonObject): AssetBuildResult {\n const images = Array.isArray(assets.images) ? assets.images.filter(isObject) : [];\n let mismatch: string | undefined;\n const image = images.find(candidate => {\n const widthMatches = slot.width === undefined || candidate.width === slot.width;\n const heightMatches = slot.height === undefined || candidate.height === slot.height;\n if (!widthMatches || !heightMatches) return false;\n const candidateMismatch = imageFixtureMismatch(candidate, slot);\n if (candidateMismatch) {\n mismatch ??= candidateMismatch;\n return false;\n }\n return true;\n });\n if (!image) {\n return { ok: false, constraint: mismatch ? `${imageConstraint(slot)}; ${mismatch}` : imageConstraint(slot) };\n }\n if (typeof image.url !== 'string') {\n return { ok: false, constraint: `${imageConstraint(slot)}, but the matching fixture has no URL` };\n }\n return {\n ok: true,\n asset: {\n asset_type: 'image',\n url: image.url,\n ...(asNumber(image.width) !== undefined ? { width: image.width } : {}),\n ...(asNumber(image.height) !== undefined ? { height: image.height } : {}),\n ...(typeof image.mime_type === 'string' ? { mime_type: image.mime_type } : {}),\n },\n };\n}\n\nfunction textFixtureMismatch(content: string, requirements: JsonObject): string | undefined {\n const supported = new Set([\n 'min_length',\n 'max_length',\n 'min_lines',\n 'max_lines',\n 'prohibited_terms',\n 'allowed_values',\n ]);\n const unsupported = Object.keys(requirements).find(key => !supported.has(key));\n if (unsupported) return `cannot verify text requirement \"${unsupported}\"`;\n\n const minLength = asNumber(requirements.min_length);\n const maxLength = asNumber(requirements.max_length);\n if (minLength !== undefined && content.length < minLength) return `requires minimum length ${minLength}`;\n if (maxLength !== undefined && content.length > maxLength) return `requires maximum length ${maxLength}`;\n\n const lines = content.split(/\\r?\\n/).length;\n const minLines = asNumber(requirements.min_lines);\n const maxLines = asNumber(requirements.max_lines);\n if (minLines !== undefined && lines < minLines) return `requires minimum line count ${minLines}`;\n if (maxLines !== undefined && lines > maxLines) return `requires maximum line count ${maxLines}`;\n\n if (Array.isArray(requirements.prohibited_terms)) {\n const prohibited = requirements.prohibited_terms.find(\n (term): term is string => typeof term === 'string' && content.toLowerCase().includes(term.toLowerCase())\n );\n if (prohibited) return `prohibits term \"${prohibited}\"`;\n }\n if (\n Array.isArray(requirements.allowed_values) &&\n !requirements.allowed_values.some(value => typeof value === 'string' && value === content)\n ) {\n return 'requires one of the declared allowed_values';\n }\n return undefined;\n}\n\nfunction buildText(slot: RequiredSlot, assets: JsonObject): AssetBuildResult {\n const text = isObject(assets.text) ? assets.text : {};\n const id = slot.id.toLowerCase();\n const fixtureCategory = {\n headline: 'headlines',\n title: 'headlines',\n description: 'descriptions',\n body: 'descriptions',\n body_text: 'descriptions',\n primary_text: 'descriptions',\n cta: 'cta',\n cta_text: 'cta',\n call_to_action: 'cta',\n }[id];\n if (fixtureCategory === undefined) {\n return {\n ok: false,\n constraint: 'slot id has no exact runner mapping to a headlines, descriptions, or CTA fixture category',\n };\n }\n const candidates = Array.isArray(text[fixtureCategory])\n ? text[fixtureCategory].filter((item): item is string => typeof item === 'string')\n : [];\n let mismatch: string | undefined;\n const content = candidates.find(candidate => {\n const candidateMismatch = textFixtureMismatch(candidate, slot.requirements);\n if (candidateMismatch) {\n mismatch ??= candidateMismatch;\n return false;\n }\n return true;\n });\n return content === undefined\n ? {\n ok: false,\n constraint: mismatch ?? `requires a ${fixtureCategory} text fixture`,\n }\n : { ok: true, asset: { asset_type: 'text', content } };\n}\n\nfunction containsUrlMacro(value: string): boolean {\n let inMacro = false;\n let hasContent = false;\n for (let index = 0; index < value.length; index += 1) {\n if (!inMacro) {\n if (value[index] === '$' && value[index + 1] === '{') {\n inMacro = true;\n hasContent = false;\n index += 1;\n }\n continue;\n }\n if (value[index] === '}') {\n if (hasContent) return true;\n inMacro = false;\n continue;\n }\n hasContent = true;\n }\n return false;\n}\n\nfunction buildUrl(slot: RequiredSlot, assets: JsonObject): AssetBuildResult {\n if (typeof assets.click_url !== 'string') return { ok: false, constraint: 'requires a click_url fixture' };\n const url = assets.click_url;\n const supported = new Set(['role', 'protocols', 'allowed_domains', 'max_length', 'macro_support']);\n const unsupported = Object.keys(slot.requirements).find(key => !supported.has(key));\n if (unsupported) return { ok: false, constraint: `cannot verify URL requirement \"${unsupported}\"` };\n const maxLength = asNumber(slot.requirements.max_length);\n if (maxLength !== undefined && url.length > maxLength) {\n return { ok: false, constraint: `requires URL maximum length ${maxLength}` };\n }\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return { ok: false, constraint: 'click_url fixture is not an absolute URL' };\n }\n if (\n Array.isArray(slot.requirements.protocols) &&\n !slot.requirements.protocols.some(protocol => protocol === parsed.protocol.replace(/:$/, ''))\n ) {\n return { ok: false, constraint: 'click_url fixture uses a disallowed protocol' };\n }\n if (\n Array.isArray(slot.requirements.allowed_domains) &&\n !slot.requirements.allowed_domains.some(domain => domain === parsed.hostname)\n ) {\n return { ok: false, constraint: 'click_url fixture uses a disallowed domain' };\n }\n if (slot.requirements.macro_support === true && !containsUrlMacro(url)) {\n return { ok: false, constraint: 'requires a URL fixture with macro support' };\n }\n return { ok: true, asset: { asset_type: 'url', url } };\n}\n\nfunction buildAsset(slot: RequiredSlot, testKit: unknown): AssetBuildResult {\n if (!isObject(testKit) || !isObject(testKit.assets)) {\n return { ok: false, constraint: 'selected test kit does not declare asset fixtures' };\n }\n const assets = testKit.assets;\n if (slot.assetType === 'image') return buildImage(slot, assets);\n if (slot.assetType === 'url') return buildUrl(slot, assets);\n if (slot.assetType === 'text') return buildText(slot, assets);\n return { ok: false, constraint: `asset type \"${slot.assetType}\" is not supported by the selected test kit` };\n}\n\nfunction buildAssets(value: unknown, context: StoryboardContext, testKit: unknown): AssetsBuildResult {\n const resolved = resolveFormat(value, context);\n if (!resolved.ok) {\n return { ok: false, failure: { reason: resolved.reason, constraint: resolved.constraint } };\n }\n const required = requiredSlots(resolved.format);\n if (!required.ok) {\n return { ok: false, failure: { reason: 'malformed_directive', constraint: required.constraint } };\n }\n\n const built: JsonObject = {};\n for (const slot of required.slots) {\n const result = buildAsset(slot, testKit);\n if (!result.ok) {\n return {\n ok: false,\n failure: {\n reason: 'fixture_unavailable',\n slotId: slot.id,\n assetType: slot.assetType,\n constraint: result.constraint,\n },\n };\n }\n built[slot.id] = result.asset;\n }\n return { ok: true, assets: built };\n}\n\nfunction expandWithDiagnostics(\n value: unknown,\n context: StoryboardContext,\n testKit: unknown,\n path: string\n): CreativeAssetExpansionResult {\n if (Array.isArray(value)) {\n const expanded = Array.from(value as unknown[]);\n for (let index = 0; index < value.length; index += 1) {\n const result = expandWithDiagnostics(value[index], context, testKit, `${path}[${index}]`);\n expanded[index] = result.value;\n if (!result.ok) return { ...result, value: expanded };\n }\n return { ok: true, value: expanded };\n }\n if (!isObject(value)) return { ok: true, value };\n\n if (Object.prototype.hasOwnProperty.call(value, BUILD_ASSETS_FROM_FORMAT_DIRECTIVE)) {\n const built = buildAssets(value[BUILD_ASSETS_FROM_FORMAT_DIRECTIVE], context, testKit);\n if (!built.ok) {\n return {\n ok: false,\n value,\n failure: {\n ...built.failure,\n path: `${path}.${BUILD_ASSETS_FROM_FORMAT_DIRECTIVE}`,\n },\n };\n }\n const siblings: JsonObject = Object.fromEntries(\n Object.entries(value).filter(([key]) => key !== BUILD_ASSETS_FROM_FORMAT_DIRECTIVE)\n );\n for (const [key, item] of Object.entries(value)) {\n if (key === BUILD_ASSETS_FROM_FORMAT_DIRECTIVE) continue;\n const result = expandWithDiagnostics(item, context, testKit, `${path}.${key}`);\n siblings[key] = result.value;\n if (!result.ok) return { ...result, value: { ...siblings, ...built.assets } };\n }\n return { ok: true, value: { ...siblings, ...built.assets } };\n }\n\n const expanded: JsonObject = { ...value };\n for (const [key, item] of Object.entries(value)) {\n const result = expandWithDiagnostics(item, context, testKit, `${path}.${key}`);\n expanded[key] = result.value;\n if (!result.ok) return { ...result, value: expanded };\n }\n return { ok: true, value: expanded };\n}\n\n/** Expand reserved storyboard creative-asset directives and preserve the first failure diagnostic. */\nexport function expandCreativeAssetDirectivesWithDiagnostics(\n value: unknown,\n context: StoryboardContext,\n testKit: unknown\n): CreativeAssetExpansionResult {\n return expandWithDiagnostics(value, context, testKit, '$');\n}\n\n/** Expand reserved storyboard creative-asset directives without mutating the fixture. */\nexport function expandCreativeAssetDirectives(value: unknown, context: StoryboardContext, testKit: unknown): unknown {\n return expandCreativeAssetDirectivesWithDiagnostics(value, context, testKit).value;\n}\n\nexport function findUnresolvedCreativeAssetDirectives(value: unknown): string[] {\n const paths: string[] = [];\n const walk = (item: unknown, path: string) => {\n if (Array.isArray(item)) {\n item.forEach((entry, index) => walk(entry, `${path}[${index}]`));\n return;\n }\n if (!isObject(item)) return;\n if (Object.prototype.hasOwnProperty.call(item, BUILD_ASSETS_FROM_FORMAT_DIRECTIVE)) {\n paths.push(`${path}.${BUILD_ASSETS_FROM_FORMAT_DIRECTIVE}`);\n }\n Object.entries(item).forEach(([key, entry]) => walk(entry, path ? `${path}.${key}` : key));\n };\n walk(value, '$');\n return paths;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,MAAM,qCAAqC;AAuClD,SAAS,SAAS,OAAqC;AACrD,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,SAAS,OAAoC;AACpD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;AAEA,SAAS,kBAAkB,OAAoC;AAC7D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,SAAO,MAAM,QAAQ,OAAO,EAAE;AAChC;AAEA,SAAS,gBAAgB,WAAoB,WAAgC;AAC3E,MAAI,CAAC,SAAS,SAAS,EAAG,QAAO;AACjC,MAAI,UAAU,OAAO,UAAU,GAAI,QAAO;AAC1C,QAAM,iBAAiB,kBAAkB,UAAU,SAAS;AAC5D,QAAM,iBAAiB,kBAAkB,UAAU,SAAS;AAC5D,SAAO,mBAAmB,UAAa,mBAAmB;AAC5D;AAEA,SAAS,cACP,OACA,SAGwF;AACxF,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,EACF;AACA,MAAI,MAAM,QAAQ,MAAM,KAAK,KAAK,MAAM,QAAQ,MAAM,MAAM,KAAK,MAAM,QAAQ,MAAM,eAAe,GAAG;AACrG,WAAO,EAAE,IAAI,MAAM,QAAQ,MAAM;AAAA,EACnC;AAEA,MAAI,OAAO,MAAM,OAAO,UAAU;AAChC,WAAO,EAAE,IAAI,OAAO,QAAQ,uBAAuB,YAAY,4CAA4C;AAAA,EAC7G;AACA,QAAM,UAAU,MAAM,QAAQ,QAAQ,OAAO,IAAI,QAAQ,UAAU,CAAC;AACpE,QAAM,SAAS,QAAQ;AAAA,IACrB,CAAC,cAAuC,SAAS,SAAS,KAAK,gBAAgB,UAAU,WAAW,KAAK;AAAA,EAC3G;AACA,MAAI,CAAC,QAAQ;AACX,UAAM,QAAQ,OAAO,MAAM,cAAc,WAAW,SAAS,MAAM,SAAS,KAAK;AACjF,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,YAAY,WAAW,MAAM,EAAE,IAAI,KAAK;AAAA,IAC1C;AAAA,EACF;AACA,QAAM,kBAAkB,SAAS,OAAO,SAAS,IAAI,OAAO,YAAY,CAAC;AACzE,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,QAAQ;AAAA,MACN,GAAG;AAAA,MACH,GAAI,SAAS,MAAM,KAAK,MAAM,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,MACpE,GAAI,SAAS,MAAM,MAAM,MAAM,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,MACvE,WAAW,EAAE,GAAG,iBAAiB,GAAG,MAAM;AAAA,IAC5C;AAAA,EACF;AACF;AAEA,SAAS,iBAAiB,QAAgC;AACxD,QAAM,WAAW,SAAS,OAAO,SAAS,IAAI,OAAO,UAAU,KAAK;AACpE,QAAM,QAAQ,OAAO,aAAa,WAAW,SAAS,MAAM,oCAAoC,IAAI;AACpG,SAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,CAAC,CAAC,GAAG,QAAQ,OAAO,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC;AAC1E;AAEA,SAAS,iBAAiB,QAAgC;AACxD,QAAM,iBAAiB,SAAS,OAAO,SAAS,IAAI,OAAO,YAAY,CAAC;AACxE,QAAM,SAAS;AAAA,IACb,OAAO,SAAS,OAAO,KAAK,KAAK,SAAS,eAAe,KAAK;AAAA,IAC9D,QAAQ,SAAS,OAAO,MAAM,KAAK,SAAS,eAAe,MAAM;AAAA,EACnE;AACA,MAAI,OAAO,UAAU,UAAa,OAAO,WAAW,OAAW,QAAO;AAEtE,QAAM,UAAU,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,UAAU,CAAC;AAClE,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,SAAS,MAAM,EAAG;AACvB,UAAM,aAAa,SAAS,OAAO,UAAU,IAAI,OAAO,aAAa;AACrE,UAAM,QAAQ,SAAS,WAAW,KAAK;AACvC,UAAM,SAAS,SAAS,WAAW,MAAM;AACzC,QAAI,UAAU,UAAa,WAAW,OAAW,QAAO,EAAE,OAAO,OAAO;AAAA,EAC1E;AAEA,SAAO,iBAAiB,MAAM;AAChC;AAEA,SAAS,eAAe,MAAkB,UAAkC;AAC1E,QAAM,eAAe,SAAS,KAAK,YAAY,IAAI,KAAK,eAAe,CAAC;AACxE,QAAM,SAAS,SAAS,aAAa,UAAU,IAAI,aAAa,aAAa;AAC7E,SAAO;AAAA,IACL,OAAO,SAAS,KAAK,KAAK,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS;AAAA,IAClE,QAAQ,SAAS,KAAK,MAAM,KAAK,SAAS,OAAO,MAAM,KAAK,SAAS;AAAA,EACvE;AACF;AAEA,SAAS,cAAc,QAAyC;AAC9D,QAAM,iBAAiB,MAAM,QAAQ,OAAO,KAAK,IAAI,OAAO,QAAQ;AACpE,QAAM,cAAc,MAAM,QAAQ,OAAO,MAAM,IAC3C,OAAO,SACP,MAAM,QAAQ,OAAO,eAAe,IAClC,OAAO,kBACP;AACN,QAAM,qBAAqB,mBAAmB,UAAa,CAAC,MAAM,QAAQ,OAAO,MAAM,KAAK,gBAAgB;AAC5G,QAAM,QAAQ,kBAAkB,eAAe,CAAC;AAChD,QAAM,WAAW,iBAAiB,MAAM;AACxC,QAAM,YAAY,mBAAmB,SAAY,UAAU,qBAAqB,oBAAoB;AAEpG,QAAM,WAA2B,CAAC;AAClC,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,YAAY,MAAM,KAAK;AAC7B,QAAI,CAAC,SAAS,SAAS,KAAM,CAAC,sBAAsB,UAAU,aAAa,KAAO;AAClF,UAAM,oBAAoB,UAAU,cAAc;AAClD,UAAM,KAAK,mBAAmB,UAAa,oBAAoB,UAAU,iBAAiB,UAAU;AACpG,UAAM,YACJ,OAAO,UAAU,eAAe,WAC5B,UAAU,aACV,oBACE,qBACA;AACR,UAAM,UAAU,mBAAmB,UAAa,oBAAoB,mBAAmB;AACvF,QAAI,OAAO,OAAO,UAAU;AAC1B,aAAO,EAAE,IAAI,OAAO,YAAY,YAAY,SAAS,IAAI,KAAK,KAAK,OAAO,oBAAoB;AAAA,IAChG;AACA,QAAI,cAAc,QAAW;AAC3B,aAAO,EAAE,IAAI,OAAO,YAAY,YAAY,SAAS,IAAI,KAAK,gCAAgC;AAAA,IAChG;AACA,UAAM,eAAe,SAAS,UAAU,YAAY,IAAI,UAAU,eAAe,CAAC;AAClF,UAAM,aAAa,eAAe,WAAW,QAAQ;AACrD,aAAS,KAAK,EAAE,IAAI,WAAW,cAAc,GAAG,WAAW,CAAC;AAAA,EAC9D;AACA,SAAO,EAAE,IAAI,MAAM,OAAO,SAAS;AACrC;AAEA,SAAS,gBAAgB,MAA4B;AACnD,MAAI,KAAK,UAAU,UAAa,KAAK,WAAW,QAAW;AACzD,WAAO,qBAAqB,KAAK,KAAK,IAAI,KAAK,MAAM;AAAA,EACvD;AACA,MAAI,KAAK,UAAU,OAAW,QAAO,8CAA8C,KAAK,KAAK;AAC7F,MAAI,KAAK,WAAW,OAAW,QAAO,+CAA+C,KAAK,MAAM;AAChG,SAAO;AACT;AAEA,SAAS,qBAAqB,WAAuB,MAAwC;AAC3F,QAAM,eAAe,KAAK;AAC1B,QAAM,YAAY,oBAAI,IAAI;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,QAAM,cAAc,OAAO,KAAK,YAAY,EAAE,KAAK,SAAO,CAAC,UAAU,IAAI,GAAG,CAAC;AAC7E,MAAI,YAAa,QAAO,oCAAoC,WAAW;AAEvE,QAAM,OAAO,OAAO,aAAa,SAAS,WAAW,aAAa,OAAO;AACzE,MAAI,SAAS,QAAQ,SAAS,WAAW,SAAS,UAAU;AAC1D,WAAO,kDAAkD,IAAI;AAAA,EAC/D;AAEA,QAAM,QAAQ,SAAS,UAAU,KAAK;AACtC,QAAM,SAAS,SAAS,UAAU,MAAM;AACxC,QAAM,WAAW,SAAS,aAAa,SAAS;AAChD,QAAM,WAAW,SAAS,aAAa,SAAS;AAChD,QAAM,YAAY,SAAS,aAAa,UAAU;AAClD,QAAM,YAAY,SAAS,aAAa,UAAU;AAClD,MAAI,aAAa,WAAc,UAAU,UAAa,QAAQ,UAAW,QAAO,0BAA0B,QAAQ;AAClH,MAAI,aAAa,WAAc,UAAU,UAAa,QAAQ,UAAW,QAAO,0BAA0B,QAAQ;AAClH,MAAI,cAAc,WAAc,WAAW,UAAa,SAAS,YAAY;AAC3E,WAAO,2BAA2B,SAAS;AAAA,EAC7C;AACA,MAAI,cAAc,WAAc,WAAW,UAAa,SAAS,YAAY;AAC3E,WAAO,2BAA2B,SAAS;AAAA,EAC7C;AAEA,MAAI,OAAO,aAAa,iBAAiB,UAAU;AACjD,UAAM,QAAQ,oCAAoC,KAAK,aAAa,YAAY;AAChF,QAAI,CAAC,SAAS,UAAU,UAAa,WAAW,QAAW;AACzD,aAAO,+BAA+B,aAAa,YAAY;AAAA,IACjE;AACA,UAAM,WAAW,OAAO,MAAM,CAAC,CAAC,IAAI,OAAO,MAAM,CAAC,CAAC;AACnD,QAAI,KAAK,IAAI,QAAQ,SAAS,QAAQ,IAAI,KAAO,QAAO,yBAAyB,aAAa,YAAY;AAAA,EAC5G;AAEA,MAAI,MAAM,QAAQ,aAAa,OAAO,GAAG;AACvC,UAAM,WAAW,OAAO,UAAU,cAAc,WAAW,UAAU,UAAU,YAAY,IAAI;AAC/F,UAAM,YAAY,SAAS,MAAM,GAAG,EAAE,CAAC,GAAG,QAAQ,QAAQ,KAAK;AAC/D,UAAM,UAAU,aAAa,QAC1B,OAAO,CAAC,SAAyB,OAAO,SAAS,QAAQ,EACzD,IAAI,UAAQ,KAAK,YAAY,EAAE,QAAQ,QAAQ,KAAK,CAAC;AACxD,QAAI,CAAC,aAAa,CAAC,QAAQ,SAAS,SAAS,EAAG,QAAO,6BAA6B,QAAQ,KAAK,IAAI,CAAC;AAAA,EACxG;AAEA,MAAI,MAAM,QAAQ,aAAa,YAAY,GAAG;AAC5C,UAAM,QAAQ,SAAS,UAAU,WAAW,KAAK;AACjD,UAAM,UAAU,aAAa,aAAa,OAAO,CAAC,SAAyB,SAAS,IAAI,MAAM,MAAS;AACvG,QAAI,CAAC,QAAQ,SAAS,KAAK,EAAG,QAAO,4BAA4B,QAAQ,KAAK,IAAI,CAAC;AAAA,EACrF;AACA,SAAO;AACT;AAEA,SAAS,WAAW,MAAoB,QAAsC;AAC5E,QAAM,SAAS,MAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,OAAO,OAAO,QAAQ,IAAI,CAAC;AAChF,MAAI;AACJ,QAAM,QAAQ,OAAO,KAAK,eAAa;AACrC,UAAM,eAAe,KAAK,UAAU,UAAa,UAAU,UAAU,KAAK;AAC1E,UAAM,gBAAgB,KAAK,WAAW,UAAa,UAAU,WAAW,KAAK;AAC7E,QAAI,CAAC,gBAAgB,CAAC,cAAe,QAAO;AAC5C,UAAM,oBAAoB,qBAAqB,WAAW,IAAI;AAC9D,QAAI,mBAAmB;AACrB,mBAAa;AACb,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AACD,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,IAAI,OAAO,YAAY,WAAW,GAAG,gBAAgB,IAAI,CAAC,KAAK,QAAQ,KAAK,gBAAgB,IAAI,EAAE;AAAA,EAC7G;AACA,MAAI,OAAO,MAAM,QAAQ,UAAU;AACjC,WAAO,EAAE,IAAI,OAAO,YAAY,GAAG,gBAAgB,IAAI,CAAC,wCAAwC;AAAA,EAClG;AACA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,MACL,YAAY;AAAA,MACZ,KAAK,MAAM;AAAA,MACX,GAAI,SAAS,MAAM,KAAK,MAAM,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,MACpE,GAAI,SAAS,MAAM,MAAM,MAAM,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,MACvE,GAAI,OAAO,MAAM,cAAc,WAAW,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,IAC9E;AAAA,EACF;AACF;AAEA,SAAS,oBAAoB,SAAiB,cAA8C;AAC1F,QAAM,YAAY,oBAAI,IAAI;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,QAAM,cAAc,OAAO,KAAK,YAAY,EAAE,KAAK,SAAO,CAAC,UAAU,IAAI,GAAG,CAAC;AAC7E,MAAI,YAAa,QAAO,mCAAmC,WAAW;AAEtE,QAAM,YAAY,SAAS,aAAa,UAAU;AAClD,QAAM,YAAY,SAAS,aAAa,UAAU;AAClD,MAAI,cAAc,UAAa,QAAQ,SAAS,UAAW,QAAO,2BAA2B,SAAS;AACtG,MAAI,cAAc,UAAa,QAAQ,SAAS,UAAW,QAAO,2BAA2B,SAAS;AAEtG,QAAM,QAAQ,QAAQ,MAAM,OAAO,EAAE;AACrC,QAAM,WAAW,SAAS,aAAa,SAAS;AAChD,QAAM,WAAW,SAAS,aAAa,SAAS;AAChD,MAAI,aAAa,UAAa,QAAQ,SAAU,QAAO,+BAA+B,QAAQ;AAC9F,MAAI,aAAa,UAAa,QAAQ,SAAU,QAAO,+BAA+B,QAAQ;AAE9F,MAAI,MAAM,QAAQ,aAAa,gBAAgB,GAAG;AAChD,UAAM,aAAa,aAAa,iBAAiB;AAAA,MAC/C,CAAC,SAAyB,OAAO,SAAS,YAAY,QAAQ,YAAY,EAAE,SAAS,KAAK,YAAY,CAAC;AAAA,IACzG;AACA,QAAI,WAAY,QAAO,mBAAmB,UAAU;AAAA,EACtD;AACA,MACE,MAAM,QAAQ,aAAa,cAAc,KACzC,CAAC,aAAa,eAAe,KAAK,WAAS,OAAO,UAAU,YAAY,UAAU,OAAO,GACzF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,UAAU,MAAoB,QAAsC;AAC3E,QAAM,OAAO,SAAS,OAAO,IAAI,IAAI,OAAO,OAAO,CAAC;AACpD,QAAM,KAAK,KAAK,GAAG,YAAY;AAC/B,QAAM,kBAAkB;AAAA,IACtB,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,WAAW;AAAA,IACX,cAAc;AAAA,IACd,KAAK;AAAA,IACL,UAAU;AAAA,IACV,gBAAgB;AAAA,EAClB,EAAE,EAAE;AACJ,MAAI,oBAAoB,QAAW;AACjC,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,YAAY;AAAA,IACd;AAAA,EACF;AACA,QAAM,aAAa,MAAM,QAAQ,KAAK,eAAe,CAAC,IAClD,KAAK,eAAe,EAAE,OAAO,CAAC,SAAyB,OAAO,SAAS,QAAQ,IAC/E,CAAC;AACL,MAAI;AACJ,QAAM,UAAU,WAAW,KAAK,eAAa;AAC3C,UAAM,oBAAoB,oBAAoB,WAAW,KAAK,YAAY;AAC1E,QAAI,mBAAmB;AACrB,mBAAa;AACb,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AACD,SAAO,YAAY,SACf;AAAA,IACE,IAAI;AAAA,IACJ,YAAY,YAAY,cAAc,eAAe;AAAA,EACvD,IACA,EAAE,IAAI,MAAM,OAAO,EAAE,YAAY,QAAQ,QAAQ,EAAE;AACzD;AAEA,SAAS,iBAAiB,OAAwB;AAChD,MAAI,UAAU;AACd,MAAI,aAAa;AACjB,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,QAAI,CAAC,SAAS;AACZ,UAAI,MAAM,KAAK,MAAM,OAAO,MAAM,QAAQ,CAAC,MAAM,KAAK;AACpD,kBAAU;AACV,qBAAa;AACb,iBAAS;AAAA,MACX;AACA;AAAA,IACF;AACA,QAAI,MAAM,KAAK,MAAM,KAAK;AACxB,UAAI,WAAY,QAAO;AACvB,gBAAU;AACV;AAAA,IACF;AACA,iBAAa;AAAA,EACf;AACA,SAAO;AACT;AAEA,SAAS,SAAS,MAAoB,QAAsC;AAC1E,MAAI,OAAO,OAAO,cAAc,SAAU,QAAO,EAAE,IAAI,OAAO,YAAY,+BAA+B;AACzG,QAAM,MAAM,OAAO;AACnB,QAAM,YAAY,oBAAI,IAAI,CAAC,QAAQ,aAAa,mBAAmB,cAAc,eAAe,CAAC;AACjG,QAAM,cAAc,OAAO,KAAK,KAAK,YAAY,EAAE,KAAK,SAAO,CAAC,UAAU,IAAI,GAAG,CAAC;AAClF,MAAI,YAAa,QAAO,EAAE,IAAI,OAAO,YAAY,kCAAkC,WAAW,IAAI;AAClG,QAAM,YAAY,SAAS,KAAK,aAAa,UAAU;AACvD,MAAI,cAAc,UAAa,IAAI,SAAS,WAAW;AACrD,WAAO,EAAE,IAAI,OAAO,YAAY,+BAA+B,SAAS,GAAG;AAAA,EAC7E;AACA,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,GAAG;AAAA,EACtB,QAAQ;AACN,WAAO,EAAE,IAAI,OAAO,YAAY,2CAA2C;AAAA,EAC7E;AACA,MACE,MAAM,QAAQ,KAAK,aAAa,SAAS,KACzC,CAAC,KAAK,aAAa,UAAU,KAAK,cAAY,aAAa,OAAO,SAAS,QAAQ,MAAM,EAAE,CAAC,GAC5F;AACA,WAAO,EAAE,IAAI,OAAO,YAAY,+CAA+C;AAAA,EACjF;AACA,MACE,MAAM,QAAQ,KAAK,aAAa,eAAe,KAC/C,CAAC,KAAK,aAAa,gBAAgB,KAAK,YAAU,WAAW,OAAO,QAAQ,GAC5E;AACA,WAAO,EAAE,IAAI,OAAO,YAAY,6CAA6C;AAAA,EAC/E;AACA,MAAI,KAAK,aAAa,kBAAkB,QAAQ,CAAC,iBAAiB,GAAG,GAAG;AACtE,WAAO,EAAE,IAAI,OAAO,YAAY,4CAA4C;AAAA,EAC9E;AACA,SAAO,EAAE,IAAI,MAAM,OAAO,EAAE,YAAY,OAAO,IAAI,EAAE;AACvD;AAEA,SAAS,WAAW,MAAoB,SAAoC;AAC1E,MAAI,CAAC,SAAS,OAAO,KAAK,CAAC,SAAS,QAAQ,MAAM,GAAG;AACnD,WAAO,EAAE,IAAI,OAAO,YAAY,oDAAoD;AAAA,EACtF;AACA,QAAM,SAAS,QAAQ;AACvB,MAAI,KAAK,cAAc,QAAS,QAAO,WAAW,MAAM,MAAM;AAC9D,MAAI,KAAK,cAAc,MAAO,QAAO,SAAS,MAAM,MAAM;AAC1D,MAAI,KAAK,cAAc,OAAQ,QAAO,UAAU,MAAM,MAAM;AAC5D,SAAO,EAAE,IAAI,OAAO,YAAY,eAAe,KAAK,SAAS,8CAA8C;AAC7G;AAEA,SAAS,YAAY,OAAgB,SAA4B,SAAqC;AACpG,QAAM,WAAW,cAAc,OAAO,OAAO;AAC7C,MAAI,CAAC,SAAS,IAAI;AAChB,WAAO,EAAE,IAAI,OAAO,SAAS,EAAE,QAAQ,SAAS,QAAQ,YAAY,SAAS,WAAW,EAAE;AAAA,EAC5F;AACA,QAAM,WAAW,cAAc,SAAS,MAAM;AAC9C,MAAI,CAAC,SAAS,IAAI;AAChB,WAAO,EAAE,IAAI,OAAO,SAAS,EAAE,QAAQ,uBAAuB,YAAY,SAAS,WAAW,EAAE;AAAA,EAClG;AAEA,QAAM,QAAoB,CAAC;AAC3B,aAAW,QAAQ,SAAS,OAAO;AACjC,UAAM,SAAS,WAAW,MAAM,OAAO;AACvC,QAAI,CAAC,OAAO,IAAI;AACd,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,QAAQ,KAAK;AAAA,UACb,WAAW,KAAK;AAAA,UAChB,YAAY,OAAO;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAK,EAAE,IAAI,OAAO;AAAA,EAC1B;AACA,SAAO,EAAE,IAAI,MAAM,QAAQ,MAAM;AACnC;AAEA,SAAS,sBACP,OACA,SACA,SACA,MAC8B;AAC9B,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,UAAMA,YAAW,MAAM,KAAK,KAAkB;AAC9C,aAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,YAAM,SAAS,sBAAsB,MAAM,KAAK,GAAG,SAAS,SAAS,GAAG,IAAI,IAAI,KAAK,GAAG;AACxF,MAAAA,UAAS,KAAK,IAAI,OAAO;AACzB,UAAI,CAAC,OAAO,GAAI,QAAO,EAAE,GAAG,QAAQ,OAAOA,UAAS;AAAA,IACtD;AACA,WAAO,EAAE,IAAI,MAAM,OAAOA,UAAS;AAAA,EACrC;AACA,MAAI,CAAC,SAAS,KAAK,EAAG,QAAO,EAAE,IAAI,MAAM,MAAM;AAE/C,MAAI,OAAO,UAAU,eAAe,KAAK,OAAO,kCAAkC,GAAG;AACnF,UAAM,QAAQ,YAAY,MAAM,kCAAkC,GAAG,SAAS,OAAO;AACrF,QAAI,CAAC,MAAM,IAAI;AACb,aAAO;AAAA,QACL,IAAI;AAAA,QACJ;AAAA,QACA,SAAS;AAAA,UACP,GAAG,MAAM;AAAA,UACT,MAAM,GAAG,IAAI,IAAI,kCAAkC;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AACA,UAAM,WAAuB,OAAO;AAAA,MAClC,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,QAAQ,kCAAkC;AAAA,IACpF;AACA,eAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC/C,UAAI,QAAQ,mCAAoC;AAChD,YAAM,SAAS,sBAAsB,MAAM,SAAS,SAAS,GAAG,IAAI,IAAI,GAAG,EAAE;AAC7E,eAAS,GAAG,IAAI,OAAO;AACvB,UAAI,CAAC,OAAO,GAAI,QAAO,EAAE,GAAG,QAAQ,OAAO,EAAE,GAAG,UAAU,GAAG,MAAM,OAAO,EAAE;AAAA,IAC9E;AACA,WAAO,EAAE,IAAI,MAAM,OAAO,EAAE,GAAG,UAAU,GAAG,MAAM,OAAO,EAAE;AAAA,EAC7D;AAEA,QAAM,WAAuB,EAAE,GAAG,MAAM;AACxC,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC/C,UAAM,SAAS,sBAAsB,MAAM,SAAS,SAAS,GAAG,IAAI,IAAI,GAAG,EAAE;AAC7E,aAAS,GAAG,IAAI,OAAO;AACvB,QAAI,CAAC,OAAO,GAAI,QAAO,EAAE,GAAG,QAAQ,OAAO,SAAS;AAAA,EACtD;AACA,SAAO,EAAE,IAAI,MAAM,OAAO,SAAS;AACrC;AAGO,SAAS,6CACd,OACA,SACA,SAC8B;AAC9B,SAAO,sBAAsB,OAAO,SAAS,SAAS,GAAG;AAC3D;AAGO,SAAS,8BAA8B,OAAgB,SAA4B,SAA2B;AACnH,SAAO,6CAA6C,OAAO,SAAS,OAAO,EAAE;AAC/E;AAEO,SAAS,sCAAsC,OAA0B;AAC9E,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,CAAC,MAAe,SAAiB;AAC5C,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAK,QAAQ,CAAC,OAAO,UAAU,KAAK,OAAO,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC;AAC/D;AAAA,IACF;AACA,QAAI,CAAC,SAAS,IAAI,EAAG;AACrB,QAAI,OAAO,UAAU,eAAe,KAAK,MAAM,kCAAkC,GAAG;AAClF,YAAM,KAAK,GAAG,IAAI,IAAI,kCAAkC,EAAE;AAAA,IAC5D;AACA,WAAO,QAAQ,IAAI,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM,KAAK,OAAO,OAAO,GAAG,IAAI,IAAI,GAAG,KAAK,GAAG,CAAC;AAAA,EAC3F;AACA,OAAK,OAAO,GAAG;AACf,SAAO;AACT;","names":["expanded"]}
|