@spacefast/common 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -0
- package/dist/brand.d.ts +15 -0
- package/dist/brand.js +24 -0
- package/dist/config/domains.d.ts +30 -0
- package/dist/config/domains.js +75 -0
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.js +3 -0
- package/dist/contracts/abuse.d.ts +93 -0
- package/dist/contracts/abuse.js +50 -0
- package/dist/contracts/access.d.ts +409 -0
- package/dist/contracts/access.js +396 -0
- package/dist/contracts/account.d.ts +28 -0
- package/dist/contracts/account.js +54 -0
- package/dist/contracts/activity.d.ts +118 -0
- package/dist/contracts/activity.js +180 -0
- package/dist/contracts/analytics.d.ts +56 -0
- package/dist/contracts/analytics.js +91 -0
- package/dist/contracts/annotations.d.ts +327 -0
- package/dist/contracts/annotations.js +234 -0
- package/dist/contracts/api-keys.d.ts +517 -0
- package/dist/contracts/api-keys.js +235 -0
- package/dist/contracts/archives.d.ts +332 -0
- package/dist/contracts/archives.js +120 -0
- package/dist/contracts/auth.d.ts +86 -0
- package/dist/contracts/auth.js +82 -0
- package/dist/contracts/beta.d.ts +106 -0
- package/dist/contracts/beta.js +104 -0
- package/dist/contracts/billing.d.ts +328 -0
- package/dist/contracts/billing.js +203 -0
- package/dist/contracts/builds.d.ts +504 -0
- package/dist/contracts/builds.js +248 -0
- package/dist/contracts/channels.d.ts +49 -0
- package/dist/contracts/channels.js +51 -0
- package/dist/contracts/common.d.ts +238 -0
- package/dist/contracts/common.js +175 -0
- package/dist/contracts/deployments.d.ts +574 -0
- package/dist/contracts/deployments.js +97 -0
- package/dist/contracts/device-auth.d.ts +194 -0
- package/dist/contracts/device-auth.js +162 -0
- package/dist/contracts/domains.d.ts +6115 -0
- package/dist/contracts/domains.js +1435 -0
- package/dist/contracts/enums.d.ts +196 -0
- package/dist/contracts/enums.js +211 -0
- package/dist/contracts/error-code-meta.d.ts +1560 -0
- package/dist/contracts/error-code-meta.js +400 -0
- package/dist/contracts/error-codes.d.ts +13 -0
- package/dist/contracts/error-codes.js +416 -0
- package/dist/contracts/events.d.ts +398 -0
- package/dist/contracts/events.js +320 -0
- package/dist/contracts/fast-domain-search.d.ts +19 -0
- package/dist/contracts/fast-domain-search.js +22 -0
- package/dist/contracts/features.d.ts +240 -0
- package/dist/contracts/features.js +406 -0
- package/dist/contracts/git.d.ts +288 -0
- package/dist/contracts/git.js +116 -0
- package/dist/contracts/ids.d.ts +35 -0
- package/dist/contracts/ids.js +45 -0
- package/dist/contracts/intercom.d.ts +6 -0
- package/dist/contracts/intercom.js +5 -0
- package/dist/contracts/internal.d.ts +103 -0
- package/dist/contracts/internal.js +92 -0
- package/dist/contracts/mcp.d.ts +788 -0
- package/dist/contracts/mcp.js +161 -0
- package/dist/contracts/me.d.ts +81 -0
- package/dist/contracts/me.js +104 -0
- package/dist/contracts/oauth-resources.d.ts +30 -0
- package/dist/contracts/oauth-resources.js +61 -0
- package/dist/contracts/operations.d.ts +54 -0
- package/dist/contracts/operations.js +14 -0
- package/dist/contracts/plan-policy.d.ts +85 -0
- package/dist/contracts/plan-policy.js +75 -0
- package/dist/contracts/platform.d.ts +359 -0
- package/dist/contracts/platform.js +216 -0
- package/dist/contracts/push-new.d.ts +156 -0
- package/dist/contracts/push-new.js +52 -0
- package/dist/contracts/quotas.d.ts +16 -0
- package/dist/contracts/quotas.js +36 -0
- package/dist/contracts/repository-connections.d.ts +231 -0
- package/dist/contracts/repository-connections.js +106 -0
- package/dist/contracts/resources.d.ts +529 -0
- package/dist/contracts/resources.js +209 -0
- package/dist/contracts/routes.d.ts +45 -0
- package/dist/contracts/routes.js +31 -0
- package/dist/contracts/runtime-api.d.ts +449 -0
- package/dist/contracts/runtime-api.js +513 -0
- package/dist/contracts/sites.d.ts +393 -0
- package/dist/contracts/sites.js +121 -0
- package/dist/contracts/slugs.d.ts +31 -0
- package/dist/contracts/slugs.js +47 -0
- package/dist/contracts/space-config.d.ts +216 -0
- package/dist/contracts/space-config.js +237 -0
- package/dist/contracts/space-theme.d.ts +25 -0
- package/dist/contracts/space-theme.js +49 -0
- package/dist/contracts/spaces.d.ts +2760 -0
- package/dist/contracts/spaces.js +589 -0
- package/dist/contracts/superadmin-activity.d.ts +205 -0
- package/dist/contracts/superadmin-activity.js +107 -0
- package/dist/contracts/superadmin-emails.d.ts +212 -0
- package/dist/contracts/superadmin-emails.js +112 -0
- package/dist/contracts/superadmin-queues.d.ts +414 -0
- package/dist/contracts/superadmin-queues.js +202 -0
- package/dist/contracts/superadmin-runtime.d.ts +27 -0
- package/dist/contracts/superadmin-runtime.js +38 -0
- package/dist/contracts/superadmin-spaces.d.ts +429 -0
- package/dist/contracts/superadmin-spaces.js +82 -0
- package/dist/contracts/superadmin-tenants.d.ts +180 -0
- package/dist/contracts/superadmin-tenants.js +117 -0
- package/dist/contracts/superadmin.d.ts +654 -0
- package/dist/contracts/superadmin.js +309 -0
- package/dist/contracts/tags.d.ts +1140 -0
- package/dist/contracts/tags.js +1050 -0
- package/dist/contracts/teams.d.ts +233 -0
- package/dist/contracts/teams.js +174 -0
- package/dist/contracts/telemetry.d.ts +2 -0
- package/dist/contracts/telemetry.js +1 -0
- package/dist/contracts/transfers.d.ts +105 -0
- package/dist/contracts/transfers.js +48 -0
- package/dist/contracts/variables.d.ts +189 -0
- package/dist/contracts/variables.js +82 -0
- package/dist/contracts/webhooks.d.ts +159 -0
- package/dist/contracts/webhooks.js +59 -0
- package/dist/contracts/zero.d.ts +1538 -0
- package/dist/contracts/zero.js +755 -0
- package/dist/docs/agent-prose.d.ts +35 -0
- package/dist/docs/agent-prose.js +153 -0
- package/dist/docs/agent-setup.d.ts +6 -0
- package/dist/docs/agent-setup.js +164 -0
- package/dist/docs/agent-solutions.d.ts +110 -0
- package/dist/docs/agent-solutions.js +181 -0
- package/dist/docs/error-docs.d.ts +12 -0
- package/dist/docs/error-docs.js +1601 -0
- package/dist/docs/skill-distribution.d.ts +12 -0
- package/dist/docs/skill-distribution.js +18 -0
- package/dist/domain-exploration.d.ts +108 -0
- package/dist/domain-exploration.js +488 -0
- package/dist/domain-normalize.d.ts +1 -0
- package/dist/domain-normalize.js +14 -0
- package/dist/domain-zones.d.ts +1 -0
- package/dist/domain-zones.js +5272 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/utils/access-policy.d.ts +39 -0
- package/dist/utils/access-policy.js +232 -0
- package/dist/utils/api.d.ts +4 -0
- package/dist/utils/api.js +13 -0
- package/dist/utils/auth-redirect.d.ts +1 -0
- package/dist/utils/auth-redirect.js +48 -0
- package/dist/utils/auth.d.ts +5 -0
- package/dist/utils/auth.js +13 -0
- package/dist/utils/build-settings.d.ts +49 -0
- package/dist/utils/build-settings.js +366 -0
- package/dist/utils/claim-token.d.ts +1 -0
- package/dist/utils/claim-token.js +9 -0
- package/dist/utils/collections.d.ts +1 -0
- package/dist/utils/collections.js +5 -0
- package/dist/utils/concurrency.d.ts +1 -0
- package/dist/utils/concurrency.js +18 -0
- package/dist/utils/content-type.d.ts +10 -0
- package/dist/utils/content-type.js +145 -0
- package/dist/utils/error-display.d.ts +7 -0
- package/dist/utils/error-display.js +42 -0
- package/dist/utils/error.d.ts +1 -0
- package/dist/utils/error.js +3 -0
- package/dist/utils/generate-space-name.d.ts +14 -0
- package/dist/utils/generate-space-name.js +95 -0
- package/dist/utils/git-repository.d.ts +5 -0
- package/dist/utils/git-repository.js +99 -0
- package/dist/utils/guards.d.ts +1 -0
- package/dist/utils/guards.js +3 -0
- package/dist/utils/publish-detection.d.ts +10 -0
- package/dist/utils/publish-detection.js +118 -0
- package/dist/utils/publish-policy.d.ts +69 -0
- package/dist/utils/publish-policy.js +429 -0
- package/dist/utils/query-client.d.ts +7 -0
- package/dist/utils/query-client.js +21 -0
- package/dist/utils/query-keys.d.ts +75 -0
- package/dist/utils/query-keys.js +78 -0
- package/dist/utils/runtime-paths.d.ts +7 -0
- package/dist/utils/runtime-paths.js +28 -0
- package/dist/utils/runtime-upload.d.ts +19 -0
- package/dist/utils/runtime-upload.js +27 -0
- package/dist/utils/slug.d.ts +5 -0
- package/dist/utils/slug.js +13 -0
- package/dist/utils/space-config.d.ts +75 -0
- package/dist/utils/space-config.js +415 -0
- package/dist/utils/space-theme.d.ts +16 -0
- package/dist/utils/space-theme.js +89 -0
- package/dist/utils/static-runtime-policy.d.ts +17 -0
- package/dist/utils/static-runtime-policy.js +103 -0
- package/dist/utils/upload-session.d.ts +34 -0
- package/dist/utils/upload-session.js +69 -0
- package/dist/utils/urls.d.ts +2 -0
- package/dist/utils/urls.js +7 -0
- package/dist/utils/version-path.d.ts +6 -0
- package/dist/utils/version-path.js +51 -0
- package/dist/utils/wpcom-auth-redirects.d.ts +14 -0
- package/dist/utils/wpcom-auth-redirects.js +49 -0
- package/dist/utils/zero-realtime-signature.d.ts +12 -0
- package/dist/utils/zero-realtime-signature.js +45 -0
- package/dist/vocabulary.d.ts +230 -0
- package/dist/vocabulary.js +218 -0
- package/package.json +58 -0
|
@@ -0,0 +1,1050 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { baseDiagnosticSchema, CursorPaginationSchema, cursorListQuerySchema, dataEnvelope, } from "./common.js";
|
|
3
|
+
export const tagVersionStatusSchema = z.enum([
|
|
4
|
+
"draft",
|
|
5
|
+
"in_review",
|
|
6
|
+
"approved",
|
|
7
|
+
"publishing",
|
|
8
|
+
"published",
|
|
9
|
+
"abandoned",
|
|
10
|
+
]);
|
|
11
|
+
export const tagEnvironmentSchema = z.enum(["production", "preview", "development"]);
|
|
12
|
+
export const tagConsentCategorySchema = z.enum([
|
|
13
|
+
"necessary",
|
|
14
|
+
"functional",
|
|
15
|
+
"analytics",
|
|
16
|
+
"marketing",
|
|
17
|
+
"personalization",
|
|
18
|
+
]);
|
|
19
|
+
export const TAG_PRIVACY_SIGNAL_CONSENT_CATEGORIES = [
|
|
20
|
+
"analytics",
|
|
21
|
+
"marketing",
|
|
22
|
+
"personalization",
|
|
23
|
+
];
|
|
24
|
+
export const TAG_CONSENT_CATEGORY_DEFINITIONS = [
|
|
25
|
+
{
|
|
26
|
+
id: "necessary",
|
|
27
|
+
label: "Necessary",
|
|
28
|
+
description: "Required for basic site delivery, security, or visitor-requested actions.",
|
|
29
|
+
defaultGranted: true,
|
|
30
|
+
required: true,
|
|
31
|
+
privacySignalDefaultDenied: false,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "functional",
|
|
35
|
+
label: "Functional",
|
|
36
|
+
description: "Supports optional site features such as chat, support, comments, or monitoring.",
|
|
37
|
+
defaultGranted: true,
|
|
38
|
+
required: false,
|
|
39
|
+
privacySignalDefaultDenied: false,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: "analytics",
|
|
43
|
+
label: "Analytics",
|
|
44
|
+
description: "Measures visits, usage, performance, funnels, or product behavior.",
|
|
45
|
+
defaultGranted: true,
|
|
46
|
+
required: false,
|
|
47
|
+
privacySignalDefaultDenied: true,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "marketing",
|
|
51
|
+
label: "Marketing",
|
|
52
|
+
description: "Supports ads, retargeting, attribution, conversion measurement, or campaigns.",
|
|
53
|
+
defaultGranted: true,
|
|
54
|
+
required: false,
|
|
55
|
+
privacySignalDefaultDenied: true,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "personalization",
|
|
59
|
+
label: "Personalization",
|
|
60
|
+
description: "Adapts content, recommendations, or experiences based on visitor behavior.",
|
|
61
|
+
defaultGranted: true,
|
|
62
|
+
required: false,
|
|
63
|
+
privacySignalDefaultDenied: true,
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
export const TAG_CONSENT_CATEGORY_IDS = TAG_CONSENT_CATEGORY_DEFINITIONS.map((category) => category.id);
|
|
67
|
+
export const DEFAULT_TAG_CONSENT_DEFAULTS = Object.fromEntries(TAG_CONSENT_CATEGORY_DEFINITIONS.map((category) => [category.id, category.defaultGranted]));
|
|
68
|
+
export const tagConsentPolicySchema = z.object({
|
|
69
|
+
version: z.literal(1).default(1),
|
|
70
|
+
categories: z.array(z.string().trim().min(1)).default(TAG_CONSENT_CATEGORY_IDS),
|
|
71
|
+
categoryDefinitions: z
|
|
72
|
+
.record(z.string(), z.object({
|
|
73
|
+
label: z.string(),
|
|
74
|
+
description: z.string(),
|
|
75
|
+
defaultGranted: z.boolean(),
|
|
76
|
+
required: z.boolean().default(false),
|
|
77
|
+
privacySignalDefaultDenied: z.boolean().default(false),
|
|
78
|
+
}))
|
|
79
|
+
.default(Object.fromEntries(TAG_CONSENT_CATEGORY_DEFINITIONS.map((category) => [
|
|
80
|
+
category.id,
|
|
81
|
+
{
|
|
82
|
+
label: category.label,
|
|
83
|
+
description: category.description,
|
|
84
|
+
defaultGranted: category.defaultGranted,
|
|
85
|
+
required: category.required,
|
|
86
|
+
privacySignalDefaultDenied: category.privacySignalDefaultDenied,
|
|
87
|
+
},
|
|
88
|
+
]))),
|
|
89
|
+
defaultByCategory: z.record(z.string(), z.boolean()).default(DEFAULT_TAG_CONSENT_DEFAULTS),
|
|
90
|
+
regionDefaults: z.record(z.string(), z.record(z.string(), z.boolean())).default({}),
|
|
91
|
+
privacySignals: z
|
|
92
|
+
.object({
|
|
93
|
+
gpc: z.boolean().default(true),
|
|
94
|
+
dnt: z.boolean().default(true),
|
|
95
|
+
categories: z
|
|
96
|
+
.array(z.string().trim().min(1))
|
|
97
|
+
.default([...TAG_PRIVACY_SIGNAL_CONSENT_CATEGORIES]),
|
|
98
|
+
})
|
|
99
|
+
.default({
|
|
100
|
+
gpc: true,
|
|
101
|
+
dnt: true,
|
|
102
|
+
categories: [...TAG_PRIVACY_SIGNAL_CONSENT_CATEGORIES],
|
|
103
|
+
}),
|
|
104
|
+
tags: z.record(z.string(), z.array(z.string())).default({}),
|
|
105
|
+
diagnostics: z.array(baseDiagnosticSchema).default([]),
|
|
106
|
+
});
|
|
107
|
+
function isTagConsentPolicyRecord(value) {
|
|
108
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
109
|
+
}
|
|
110
|
+
export function isKnownTagConsentCategory(value) {
|
|
111
|
+
return tagConsentCategorySchema.safeParse(value).success;
|
|
112
|
+
}
|
|
113
|
+
export function mergeTagConsentPolicyInputs(...policies) {
|
|
114
|
+
const merged = {};
|
|
115
|
+
for (const policy of policies) {
|
|
116
|
+
if (!isTagConsentPolicyRecord(policy))
|
|
117
|
+
continue;
|
|
118
|
+
for (const [key, value] of Object.entries(policy)) {
|
|
119
|
+
if (key !== "defaultByCategory" &&
|
|
120
|
+
key !== "regionDefaults" &&
|
|
121
|
+
key !== "privacySignals" &&
|
|
122
|
+
key !== "tags" &&
|
|
123
|
+
key !== "categories" &&
|
|
124
|
+
key !== "categoryDefinitions") {
|
|
125
|
+
merged[key] = value;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (isTagConsentPolicyRecord(policy.categoryDefinitions)) {
|
|
129
|
+
const nextCategoryDefinitions = {
|
|
130
|
+
...(isTagConsentPolicyRecord(merged.categoryDefinitions) ? merged.categoryDefinitions : {}),
|
|
131
|
+
};
|
|
132
|
+
for (const [category, definition] of Object.entries(policy.categoryDefinitions)) {
|
|
133
|
+
nextCategoryDefinitions[category] = {
|
|
134
|
+
...(isTagConsentPolicyRecord(nextCategoryDefinitions[category])
|
|
135
|
+
? nextCategoryDefinitions[category]
|
|
136
|
+
: {}),
|
|
137
|
+
...(isTagConsentPolicyRecord(definition) ? definition : {}),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
merged.categoryDefinitions = nextCategoryDefinitions;
|
|
141
|
+
}
|
|
142
|
+
if (isTagConsentPolicyRecord(policy.defaultByCategory)) {
|
|
143
|
+
merged.defaultByCategory = {
|
|
144
|
+
...(isTagConsentPolicyRecord(merged.defaultByCategory) ? merged.defaultByCategory : {}),
|
|
145
|
+
...policy.defaultByCategory,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (isTagConsentPolicyRecord(policy.regionDefaults)) {
|
|
149
|
+
const nextRegionDefaults = {
|
|
150
|
+
...(isTagConsentPolicyRecord(merged.regionDefaults) ? merged.regionDefaults : {}),
|
|
151
|
+
};
|
|
152
|
+
for (const [region, defaults] of Object.entries(policy.regionDefaults)) {
|
|
153
|
+
nextRegionDefaults[region] = {
|
|
154
|
+
...(isTagConsentPolicyRecord(nextRegionDefaults[region])
|
|
155
|
+
? nextRegionDefaults[region]
|
|
156
|
+
: {}),
|
|
157
|
+
...(isTagConsentPolicyRecord(defaults) ? defaults : {}),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
merged.regionDefaults = nextRegionDefaults;
|
|
161
|
+
}
|
|
162
|
+
if (isTagConsentPolicyRecord(policy.privacySignals)) {
|
|
163
|
+
merged.privacySignals = {
|
|
164
|
+
...(isTagConsentPolicyRecord(merged.privacySignals) ? merged.privacySignals : {}),
|
|
165
|
+
...policy.privacySignals,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (isTagConsentPolicyRecord(policy.tags)) {
|
|
169
|
+
merged.tags = {
|
|
170
|
+
...(isTagConsentPolicyRecord(merged.tags) ? merged.tags : {}),
|
|
171
|
+
...policy.tags,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
if (Array.isArray(policy.categories)) {
|
|
175
|
+
const categories = new Set(Array.isArray(merged.categories)
|
|
176
|
+
? merged.categories.filter((item) => typeof item === "string")
|
|
177
|
+
: []);
|
|
178
|
+
for (const category of policy.categories) {
|
|
179
|
+
if (typeof category === "string")
|
|
180
|
+
categories.add(category);
|
|
181
|
+
}
|
|
182
|
+
merged.categories = [...categories];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
186
|
+
}
|
|
187
|
+
export const tagGraphSchema = z
|
|
188
|
+
.object({
|
|
189
|
+
format: z.literal("spacefast.tag_graph.v1").default("spacefast.tag_graph.v1"),
|
|
190
|
+
tags: z.array(z.record(z.string(), z.unknown())).default([]),
|
|
191
|
+
triggers: z.array(z.record(z.string(), z.unknown())).default([]),
|
|
192
|
+
variables: z.array(z.record(z.string(), z.unknown())).default([]),
|
|
193
|
+
systemModules: z.record(z.string(), z.unknown()).default({}),
|
|
194
|
+
consentPolicy: z.record(z.string(), z.unknown()).optional(),
|
|
195
|
+
})
|
|
196
|
+
.passthrough();
|
|
197
|
+
export const emptyTagGraph = {
|
|
198
|
+
format: "spacefast.tag_graph.v1",
|
|
199
|
+
tags: [],
|
|
200
|
+
triggers: [],
|
|
201
|
+
variables: [],
|
|
202
|
+
systemModules: {},
|
|
203
|
+
};
|
|
204
|
+
export const tagValidationResultSchema = z.object({
|
|
205
|
+
valid: z.boolean(),
|
|
206
|
+
diagnostics: z.array(baseDiagnosticSchema),
|
|
207
|
+
requiredApprovals: z.array(z.string()),
|
|
208
|
+
graphRevision: z.number().int().positive(),
|
|
209
|
+
});
|
|
210
|
+
export const tagVersionSchema = z.object({
|
|
211
|
+
id: z.string(),
|
|
212
|
+
tagSetId: z.string(),
|
|
213
|
+
versionNumber: z.number().int().positive(),
|
|
214
|
+
baseVersionId: z.string().nullable(),
|
|
215
|
+
status: tagVersionStatusSchema,
|
|
216
|
+
title: z.string(),
|
|
217
|
+
description: z.string().nullable(),
|
|
218
|
+
graph: tagGraphSchema,
|
|
219
|
+
graphRevision: z.number().int().positive(),
|
|
220
|
+
validation: tagValidationResultSchema,
|
|
221
|
+
effectiveInputDigest: z.string().nullable(),
|
|
222
|
+
staticDigest: z.string().nullable(),
|
|
223
|
+
dynamicDigest: z.string().nullable(),
|
|
224
|
+
sdkRevision: z.string().nullable(),
|
|
225
|
+
createdAt: z.string(),
|
|
226
|
+
updatedAt: z.string(),
|
|
227
|
+
publishedAt: z.string().nullable(),
|
|
228
|
+
immutableAt: z.string().nullable(),
|
|
229
|
+
});
|
|
230
|
+
export const tagVersionListQuerySchema = cursorListQuerySchema.extend({
|
|
231
|
+
status: tagVersionStatusSchema.optional(),
|
|
232
|
+
});
|
|
233
|
+
export const tagVersionListResponseSchema = z.object({
|
|
234
|
+
data: z.array(tagVersionSchema),
|
|
235
|
+
pagination: CursorPaginationSchema,
|
|
236
|
+
});
|
|
237
|
+
export const tagVersionResponseSchema = dataEnvelope(tagVersionSchema);
|
|
238
|
+
export const tagVersionCreateSchema = z.object({
|
|
239
|
+
title: z.string().trim().min(1).max(255).default("Draft tag version"),
|
|
240
|
+
description: z.string().trim().max(4_000).nullable().optional(),
|
|
241
|
+
baseVersionId: z.string().trim().min(1).nullable().optional(),
|
|
242
|
+
graph: tagGraphSchema.optional(),
|
|
243
|
+
});
|
|
244
|
+
export const tagVersionPatchSchema = z.object({
|
|
245
|
+
title: z.string().trim().min(1).max(255).optional(),
|
|
246
|
+
description: z.string().trim().max(4_000).nullable().optional(),
|
|
247
|
+
});
|
|
248
|
+
export const tagGraphResponseSchema = dataEnvelope(z.object({
|
|
249
|
+
versionId: z.string(),
|
|
250
|
+
graph: tagGraphSchema,
|
|
251
|
+
graphRevision: z.number().int().positive(),
|
|
252
|
+
}));
|
|
253
|
+
export const tagGraphPutSchema = z.object({
|
|
254
|
+
graph: tagGraphSchema,
|
|
255
|
+
});
|
|
256
|
+
export const tagGraphPatchSchema = z.object({
|
|
257
|
+
baseGraphRevision: z.number().int().positive(),
|
|
258
|
+
operations: z
|
|
259
|
+
.array(z.object({
|
|
260
|
+
op: z.enum(["replace"]),
|
|
261
|
+
path: z.enum(["graph"]),
|
|
262
|
+
value: tagGraphSchema,
|
|
263
|
+
}))
|
|
264
|
+
.length(1),
|
|
265
|
+
});
|
|
266
|
+
export const tagValidateResponseSchema = dataEnvelope(tagValidationResultSchema);
|
|
267
|
+
export const tagDiffSchema = z.object({
|
|
268
|
+
baseVersionId: z.string().nullable(),
|
|
269
|
+
targetVersionId: z.string(),
|
|
270
|
+
addedTagIds: z.array(z.string()),
|
|
271
|
+
removedTagIds: z.array(z.string()),
|
|
272
|
+
changedTagIds: z.array(z.string()),
|
|
273
|
+
graphRevision: z.number().int().positive(),
|
|
274
|
+
});
|
|
275
|
+
export const tagDiffResponseSchema = dataEnvelope(tagDiffSchema);
|
|
276
|
+
export const tagReleaseSchema = z.object({
|
|
277
|
+
id: z.string(),
|
|
278
|
+
tagSetId: z.string(),
|
|
279
|
+
environment: tagEnvironmentSchema,
|
|
280
|
+
versionId: z.string(),
|
|
281
|
+
previousVersionId: z.string().nullable(),
|
|
282
|
+
sdkRevision: z.string(),
|
|
283
|
+
staticDigest: z.string(),
|
|
284
|
+
releaseNotes: z.string().nullable(),
|
|
285
|
+
releasedAt: z.string(),
|
|
286
|
+
});
|
|
287
|
+
export const tagReleaseListResponseSchema = dataEnvelope(z.array(tagReleaseSchema));
|
|
288
|
+
export const tagReleaseResponseSchema = dataEnvelope(tagReleaseSchema.extend({
|
|
289
|
+
artifact: z
|
|
290
|
+
.object({
|
|
291
|
+
id: z.string(),
|
|
292
|
+
revision: z.string(),
|
|
293
|
+
status: z.enum(["compiling", "ready", "failed", "superseded"]),
|
|
294
|
+
})
|
|
295
|
+
.nullable(),
|
|
296
|
+
}));
|
|
297
|
+
export const tagInheritanceSchema = z.object({
|
|
298
|
+
spaceId: z.string(),
|
|
299
|
+
teamId: z.string().nullable(),
|
|
300
|
+
inherited: z.boolean(),
|
|
301
|
+
teamTagSetId: z.string().nullable(),
|
|
302
|
+
overrides: z.array(z.object({
|
|
303
|
+
tagId: z.string(),
|
|
304
|
+
disabled: z.boolean().default(false),
|
|
305
|
+
reason: z.string().nullable().default(null),
|
|
306
|
+
})),
|
|
307
|
+
});
|
|
308
|
+
export const tagInheritanceResponseSchema = dataEnvelope(tagInheritanceSchema);
|
|
309
|
+
export const tagInheritancePatchSchema = z.object({
|
|
310
|
+
inherited: z.boolean().optional(),
|
|
311
|
+
overrides: z
|
|
312
|
+
.array(z.object({
|
|
313
|
+
tagId: z.string().trim().min(1),
|
|
314
|
+
disabled: z.boolean().default(false),
|
|
315
|
+
reason: z.string().trim().max(500).nullable().optional(),
|
|
316
|
+
}))
|
|
317
|
+
.optional(),
|
|
318
|
+
});
|
|
319
|
+
export const tagActivityEventSchema = z.object({
|
|
320
|
+
id: z.string(),
|
|
321
|
+
type: z.string(),
|
|
322
|
+
versionId: z.string().nullable(),
|
|
323
|
+
environment: tagEnvironmentSchema.nullable(),
|
|
324
|
+
message: z.string(),
|
|
325
|
+
actor: z.record(z.string(), z.unknown()).nullable(),
|
|
326
|
+
createdAt: z.string(),
|
|
327
|
+
});
|
|
328
|
+
export const tagActivityResponseSchema = dataEnvelope(z.array(tagActivityEventSchema));
|
|
329
|
+
export const tagEffectiveTagResponseSchema = dataEnvelope(z.object({
|
|
330
|
+
tag: z.record(z.string(), z.unknown()),
|
|
331
|
+
environment: tagEnvironmentSchema,
|
|
332
|
+
source: z.enum(["system", "team", "space", "unknown"]),
|
|
333
|
+
}));
|
|
334
|
+
export const tagReleasePutSchema = z.object({
|
|
335
|
+
versionId: z.string().trim().min(1),
|
|
336
|
+
expectedCurrentVersionId: z.string().trim().min(1).nullable().optional(),
|
|
337
|
+
releaseNotes: z.string().trim().max(4_000).nullable().optional(),
|
|
338
|
+
});
|
|
339
|
+
export const tagApplySchema = z.object({
|
|
340
|
+
config: z.unknown(),
|
|
341
|
+
title: z.string().trim().min(1).max(255).optional(),
|
|
342
|
+
description: z.string().trim().max(4_000).nullable().optional(),
|
|
343
|
+
submit: z.boolean().default(false),
|
|
344
|
+
releaseEnvironment: tagEnvironmentSchema.optional(),
|
|
345
|
+
expectedCurrentVersionId: z.string().trim().min(1).nullable().optional(),
|
|
346
|
+
});
|
|
347
|
+
export const tagApplyResponseSchema = dataEnvelope(z.object({
|
|
348
|
+
version: tagVersionSchema,
|
|
349
|
+
validation: tagValidationResultSchema,
|
|
350
|
+
release: tagReleaseSchema
|
|
351
|
+
.extend({
|
|
352
|
+
artifact: z
|
|
353
|
+
.object({
|
|
354
|
+
id: z.string(),
|
|
355
|
+
revision: z.string(),
|
|
356
|
+
status: z.enum(["compiling", "ready", "failed", "superseded"]),
|
|
357
|
+
})
|
|
358
|
+
.nullable(),
|
|
359
|
+
})
|
|
360
|
+
.nullable(),
|
|
361
|
+
}));
|
|
362
|
+
export const tagPreviewSessionSchema = z.object({
|
|
363
|
+
id: z.string(),
|
|
364
|
+
versionId: z.string(),
|
|
365
|
+
environment: tagEnvironmentSchema,
|
|
366
|
+
previewUrl: z.string(),
|
|
367
|
+
sdkRevision: z.string(),
|
|
368
|
+
cacheMode: z.literal("public, max-age=0, s-maxage=60, must-revalidate"),
|
|
369
|
+
websocket: z.object({ enabled: z.boolean() }),
|
|
370
|
+
createdAt: z.string(),
|
|
371
|
+
expiresAt: z.string(),
|
|
372
|
+
revokedAt: z.string().nullable(),
|
|
373
|
+
});
|
|
374
|
+
export const tagPreviewSessionResponseSchema = dataEnvelope(tagPreviewSessionSchema);
|
|
375
|
+
export const tagPreviewSessionCreateSchema = z.object({
|
|
376
|
+
url: z.string().url().optional(),
|
|
377
|
+
ttlSeconds: z.number().int().min(60).max(86_400).default(3_600),
|
|
378
|
+
environment: tagEnvironmentSchema.default("production"),
|
|
379
|
+
});
|
|
380
|
+
export const tagDebugSessionCreateSchema = tagPreviewSessionCreateSchema;
|
|
381
|
+
export const tagTriggerPresetSchema = z.enum([
|
|
382
|
+
"page_view",
|
|
383
|
+
"outbound_click",
|
|
384
|
+
"form_submit",
|
|
385
|
+
"file_download",
|
|
386
|
+
"scroll_depth",
|
|
387
|
+
]);
|
|
388
|
+
export const TAG_TRIGGER_PRESETS = [
|
|
389
|
+
{
|
|
390
|
+
id: "page_view",
|
|
391
|
+
triggerId: "preset.page_view",
|
|
392
|
+
name: "Page view",
|
|
393
|
+
description: "Runs when the page is ready.",
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
id: "outbound_click",
|
|
397
|
+
triggerId: "preset.outbound_click",
|
|
398
|
+
name: "Outbound click",
|
|
399
|
+
description: "Runs when a visitor clicks a link to another site.",
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
id: "form_submit",
|
|
403
|
+
triggerId: "preset.form_submit",
|
|
404
|
+
name: "Form submit",
|
|
405
|
+
description: "Runs when a visitor submits a form.",
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
id: "file_download",
|
|
409
|
+
triggerId: "preset.file_download",
|
|
410
|
+
name: "File download",
|
|
411
|
+
description: "Runs when a visitor clicks a downloadable file link.",
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
id: "scroll_depth",
|
|
415
|
+
triggerId: "preset.scroll_depth",
|
|
416
|
+
name: "Scroll depth",
|
|
417
|
+
description: "Runs as visitors reach 25%, 50%, 75%, and 90% page depth.",
|
|
418
|
+
},
|
|
419
|
+
];
|
|
420
|
+
export const tagTemplateIdSchema = z.enum([
|
|
421
|
+
"google-analytics",
|
|
422
|
+
"google-tag-manager",
|
|
423
|
+
"meta-pixel",
|
|
424
|
+
"tiktok-pixel",
|
|
425
|
+
"linkedin-insight",
|
|
426
|
+
"posthog",
|
|
427
|
+
"plausible",
|
|
428
|
+
"amplitude",
|
|
429
|
+
"segment",
|
|
430
|
+
"sentry-browser",
|
|
431
|
+
"intercom",
|
|
432
|
+
"hubspot",
|
|
433
|
+
"crisp",
|
|
434
|
+
"custom-javascript",
|
|
435
|
+
]);
|
|
436
|
+
const tagTemplateFieldSchema = z.object({
|
|
437
|
+
key: z.string(),
|
|
438
|
+
label: z.string(),
|
|
439
|
+
kind: z.enum(["text", "url", "secret", "textarea", "boolean"]).default("text"),
|
|
440
|
+
required: z.boolean().default(false),
|
|
441
|
+
placeholder: z.string().optional(),
|
|
442
|
+
help: z.string().optional(),
|
|
443
|
+
defaultValue: z.union([z.string(), z.boolean()]).optional(),
|
|
444
|
+
});
|
|
445
|
+
export const tagTemplateDefinitionSchema = z.object({
|
|
446
|
+
id: tagTemplateIdSchema,
|
|
447
|
+
name: z.string(),
|
|
448
|
+
category: z.enum(["analytics", "advertising", "product", "support", "monitoring", "custom"]),
|
|
449
|
+
description: z.string(),
|
|
450
|
+
defaultTriggers: z.array(tagTriggerPresetSchema),
|
|
451
|
+
consentCategories: z.array(tagConsentCategorySchema),
|
|
452
|
+
fields: z.array(tagTemplateFieldSchema),
|
|
453
|
+
scriptHosts: z.array(z.string()).default([]),
|
|
454
|
+
advanced: z.boolean().default(false),
|
|
455
|
+
});
|
|
456
|
+
export const tagTemplateSelectionSchema = z.object({
|
|
457
|
+
templateId: tagTemplateIdSchema,
|
|
458
|
+
id: z.string().trim().min(1).max(160).optional(),
|
|
459
|
+
name: z.string().trim().min(1).max(160).optional(),
|
|
460
|
+
enabled: z.boolean().default(true),
|
|
461
|
+
config: z.record(z.string(), z.unknown()).default({}),
|
|
462
|
+
triggers: z.array(tagTriggerPresetSchema).optional(),
|
|
463
|
+
consentCategories: z.array(tagConsentCategorySchema).optional(),
|
|
464
|
+
environments: z.array(tagEnvironmentSchema).optional(),
|
|
465
|
+
schedule: z
|
|
466
|
+
.object({
|
|
467
|
+
activeFrom: z.string().trim().min(1).optional(),
|
|
468
|
+
activeUntil: z.string().trim().min(1).optional(),
|
|
469
|
+
})
|
|
470
|
+
.optional(),
|
|
471
|
+
});
|
|
472
|
+
export const tagTemplateListResponseSchema = dataEnvelope(z.object({
|
|
473
|
+
templates: z.array(tagTemplateDefinitionSchema),
|
|
474
|
+
triggers: z.array(z.object({
|
|
475
|
+
id: tagTriggerPresetSchema,
|
|
476
|
+
triggerId: z.string(),
|
|
477
|
+
name: z.string(),
|
|
478
|
+
description: z.string(),
|
|
479
|
+
})),
|
|
480
|
+
}));
|
|
481
|
+
export const tagConsentPolicyResponseSchema = dataEnvelope(z.object({
|
|
482
|
+
environment: tagEnvironmentSchema,
|
|
483
|
+
versionId: z.string().nullable(),
|
|
484
|
+
graphRevision: z.number().int().nonnegative(),
|
|
485
|
+
policy: tagConsentPolicySchema,
|
|
486
|
+
}));
|
|
487
|
+
export const tagTemplateGraphSchema = z.object({
|
|
488
|
+
templates: z.array(tagTemplateSelectionSchema).default([]),
|
|
489
|
+
eventPresets: z.array(tagTriggerPresetSchema).default([]),
|
|
490
|
+
graph: tagGraphSchema.optional(),
|
|
491
|
+
});
|
|
492
|
+
const TAG_TEMPLATE_DEFINITION_INPUTS = [
|
|
493
|
+
{
|
|
494
|
+
id: "google-analytics",
|
|
495
|
+
name: "Google Analytics",
|
|
496
|
+
category: "analytics",
|
|
497
|
+
description: "Measure page views and events with GA4.",
|
|
498
|
+
defaultTriggers: ["page_view"],
|
|
499
|
+
consentCategories: ["analytics"],
|
|
500
|
+
scriptHosts: ["www.googletagmanager.com"],
|
|
501
|
+
fields: [
|
|
502
|
+
{
|
|
503
|
+
key: "measurementId",
|
|
504
|
+
label: "Measurement ID",
|
|
505
|
+
required: true,
|
|
506
|
+
placeholder: "G-XXXXXXXXXX",
|
|
507
|
+
},
|
|
508
|
+
],
|
|
509
|
+
advanced: false,
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
id: "google-tag-manager",
|
|
513
|
+
name: "Google Tag Manager",
|
|
514
|
+
category: "analytics",
|
|
515
|
+
description: "Load a GTM web container.",
|
|
516
|
+
defaultTriggers: ["page_view"],
|
|
517
|
+
consentCategories: ["analytics", "marketing"],
|
|
518
|
+
scriptHosts: ["www.googletagmanager.com"],
|
|
519
|
+
fields: [
|
|
520
|
+
{
|
|
521
|
+
key: "containerId",
|
|
522
|
+
label: "Container ID",
|
|
523
|
+
required: true,
|
|
524
|
+
placeholder: "GTM-XXXXXXX",
|
|
525
|
+
},
|
|
526
|
+
],
|
|
527
|
+
advanced: false,
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
id: "meta-pixel",
|
|
531
|
+
name: "Meta Pixel",
|
|
532
|
+
category: "advertising",
|
|
533
|
+
description: "Load Meta Pixel and send PageView plus selected events.",
|
|
534
|
+
defaultTriggers: ["page_view"],
|
|
535
|
+
consentCategories: ["marketing"],
|
|
536
|
+
scriptHosts: ["connect.facebook.net"],
|
|
537
|
+
fields: [{ key: "pixelId", label: "Pixel ID", required: true, placeholder: "1234567890" }],
|
|
538
|
+
advanced: false,
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
id: "tiktok-pixel",
|
|
542
|
+
name: "TikTok Pixel",
|
|
543
|
+
category: "advertising",
|
|
544
|
+
description: "Load TikTok Pixel and send selected events.",
|
|
545
|
+
defaultTriggers: ["page_view"],
|
|
546
|
+
consentCategories: ["marketing"],
|
|
547
|
+
scriptHosts: ["analytics.tiktok.com"],
|
|
548
|
+
fields: [{ key: "pixelId", label: "Pixel ID", required: true, placeholder: "C000000000" }],
|
|
549
|
+
advanced: false,
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
id: "linkedin-insight",
|
|
553
|
+
name: "LinkedIn Insight Tag",
|
|
554
|
+
category: "advertising",
|
|
555
|
+
description: "Install LinkedIn Insight for ads attribution.",
|
|
556
|
+
defaultTriggers: ["page_view"],
|
|
557
|
+
consentCategories: ["marketing"],
|
|
558
|
+
scriptHosts: ["snap.licdn.com"],
|
|
559
|
+
fields: [
|
|
560
|
+
{ key: "partnerId", label: "Partner ID", required: true, placeholder: "123456" },
|
|
561
|
+
{ key: "conversionId", label: "Conversion ID", required: false, placeholder: "Optional" },
|
|
562
|
+
],
|
|
563
|
+
advanced: false,
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
id: "posthog",
|
|
567
|
+
name: "PostHog",
|
|
568
|
+
category: "product",
|
|
569
|
+
description: "Load PostHog product analytics.",
|
|
570
|
+
defaultTriggers: ["page_view"],
|
|
571
|
+
consentCategories: ["analytics"],
|
|
572
|
+
scriptHosts: ["us.i.posthog.com", "eu.i.posthog.com", "app.posthog.com"],
|
|
573
|
+
fields: [
|
|
574
|
+
{ key: "apiKey", label: "Project API key", required: true, placeholder: "phc_..." },
|
|
575
|
+
{
|
|
576
|
+
key: "host",
|
|
577
|
+
label: "Host",
|
|
578
|
+
kind: "url",
|
|
579
|
+
required: false,
|
|
580
|
+
placeholder: "https://us.i.posthog.com",
|
|
581
|
+
},
|
|
582
|
+
],
|
|
583
|
+
advanced: false,
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
id: "plausible",
|
|
587
|
+
name: "Plausible",
|
|
588
|
+
category: "analytics",
|
|
589
|
+
description: "Load Plausible analytics.",
|
|
590
|
+
defaultTriggers: ["page_view"],
|
|
591
|
+
consentCategories: ["analytics"],
|
|
592
|
+
scriptHosts: ["plausible.io"],
|
|
593
|
+
fields: [
|
|
594
|
+
{ key: "domain", label: "Domain", required: true, placeholder: "example.com" },
|
|
595
|
+
{
|
|
596
|
+
key: "scriptUrl",
|
|
597
|
+
label: "Script URL",
|
|
598
|
+
kind: "url",
|
|
599
|
+
required: false,
|
|
600
|
+
placeholder: "https://plausible.io/js/script.js",
|
|
601
|
+
},
|
|
602
|
+
],
|
|
603
|
+
advanced: false,
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
id: "amplitude",
|
|
607
|
+
name: "Amplitude",
|
|
608
|
+
category: "product",
|
|
609
|
+
description: "Load Amplitude Browser SDK from CDN.",
|
|
610
|
+
defaultTriggers: ["page_view"],
|
|
611
|
+
consentCategories: ["analytics"],
|
|
612
|
+
scriptHosts: ["cdn.amplitude.com"],
|
|
613
|
+
fields: [{ key: "apiKey", label: "API key", required: true, placeholder: "abcdef..." }],
|
|
614
|
+
advanced: false,
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
id: "segment",
|
|
618
|
+
name: "Segment",
|
|
619
|
+
category: "analytics",
|
|
620
|
+
description: "Load Segment Analytics.js.",
|
|
621
|
+
defaultTriggers: ["page_view"],
|
|
622
|
+
consentCategories: ["analytics", "marketing"],
|
|
623
|
+
scriptHosts: ["cdn.segment.com"],
|
|
624
|
+
fields: [{ key: "writeKey", label: "Write key", required: true, placeholder: "abc123" }],
|
|
625
|
+
advanced: false,
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
id: "sentry-browser",
|
|
629
|
+
name: "Sentry Browser",
|
|
630
|
+
category: "monitoring",
|
|
631
|
+
description: "Load Sentry browser monitoring from the Sentry CDN loader.",
|
|
632
|
+
defaultTriggers: ["page_view"],
|
|
633
|
+
consentCategories: ["functional"],
|
|
634
|
+
scriptHosts: ["js.sentry-cdn.com"],
|
|
635
|
+
fields: [{ key: "loaderKey", label: "Loader key", required: true, placeholder: "abcd1234" }],
|
|
636
|
+
advanced: true,
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
id: "intercom",
|
|
640
|
+
name: "Intercom",
|
|
641
|
+
category: "support",
|
|
642
|
+
description: "Load Intercom Messenger.",
|
|
643
|
+
defaultTriggers: ["page_view"],
|
|
644
|
+
consentCategories: ["functional"],
|
|
645
|
+
scriptHosts: ["widget.intercom.io"],
|
|
646
|
+
fields: [{ key: "appId", label: "App ID", required: true, placeholder: "abc123" }],
|
|
647
|
+
advanced: false,
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
id: "hubspot",
|
|
651
|
+
name: "HubSpot",
|
|
652
|
+
category: "support",
|
|
653
|
+
description: "Load HubSpot tracking code.",
|
|
654
|
+
defaultTriggers: ["page_view"],
|
|
655
|
+
consentCategories: ["marketing"],
|
|
656
|
+
scriptHosts: ["js.hs-scripts.com"],
|
|
657
|
+
fields: [{ key: "portalId", label: "Portal ID", required: true, placeholder: "123456" }],
|
|
658
|
+
advanced: false,
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
id: "crisp",
|
|
662
|
+
name: "Crisp",
|
|
663
|
+
category: "support",
|
|
664
|
+
description: "Load Crisp chat.",
|
|
665
|
+
defaultTriggers: ["page_view"],
|
|
666
|
+
consentCategories: ["functional"],
|
|
667
|
+
scriptHosts: ["client.crisp.chat"],
|
|
668
|
+
fields: [{ key: "websiteId", label: "Website ID", required: true, placeholder: "uuid" }],
|
|
669
|
+
advanced: false,
|
|
670
|
+
},
|
|
671
|
+
{
|
|
672
|
+
id: "custom-javascript",
|
|
673
|
+
name: "Custom JavaScript",
|
|
674
|
+
category: "custom",
|
|
675
|
+
description: "Run your own script with consent and trigger controls.",
|
|
676
|
+
defaultTriggers: ["page_view"],
|
|
677
|
+
consentCategories: ["functional"],
|
|
678
|
+
scriptHosts: [],
|
|
679
|
+
fields: [
|
|
680
|
+
{ key: "name", label: "Name", required: false, placeholder: "Custom JavaScript" },
|
|
681
|
+
{ key: "code", label: "JavaScript", kind: "textarea", required: true },
|
|
682
|
+
],
|
|
683
|
+
advanced: true,
|
|
684
|
+
},
|
|
685
|
+
];
|
|
686
|
+
export const TAG_TEMPLATE_DEFINITIONS = TAG_TEMPLATE_DEFINITION_INPUTS.map((template) => tagTemplateDefinitionSchema.parse(template));
|
|
687
|
+
const TEMPLATE_BY_ID = new Map(TAG_TEMPLATE_DEFINITIONS.map((template) => [template.id, template]));
|
|
688
|
+
export function listTagTemplates() {
|
|
689
|
+
return {
|
|
690
|
+
templates: TAG_TEMPLATE_DEFINITIONS,
|
|
691
|
+
triggers: TAG_TRIGGER_PRESETS,
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
export function tagTemplateById(id) {
|
|
695
|
+
return TEMPLATE_BY_ID.get(id) ?? null;
|
|
696
|
+
}
|
|
697
|
+
function templateFieldValue(config, key) {
|
|
698
|
+
const value = config[key];
|
|
699
|
+
return typeof value === "string" ? value.trim() : "";
|
|
700
|
+
}
|
|
701
|
+
function safeTagIdPart(value) {
|
|
702
|
+
return value
|
|
703
|
+
.trim()
|
|
704
|
+
.toLowerCase()
|
|
705
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
706
|
+
.replace(/^-+|-+$/g, "")
|
|
707
|
+
.slice(0, 64);
|
|
708
|
+
}
|
|
709
|
+
function htmlScript(code) {
|
|
710
|
+
return /^\s*<script\b[^>]*>[\s\S]*<\/script>\s*$/i.test(code)
|
|
711
|
+
? code
|
|
712
|
+
: `<script>\n${code}\n</script>`;
|
|
713
|
+
}
|
|
714
|
+
function eventNameExpression(templateName) {
|
|
715
|
+
return [
|
|
716
|
+
"(function(){",
|
|
717
|
+
"var sf=window.__spacefast||{};",
|
|
718
|
+
"var ev=sf.event||{};",
|
|
719
|
+
`return ev.type||${JSON.stringify(templateName)};`,
|
|
720
|
+
"})()",
|
|
721
|
+
].join("");
|
|
722
|
+
}
|
|
723
|
+
function eventDetailExpression() {
|
|
724
|
+
return [
|
|
725
|
+
"(function(){",
|
|
726
|
+
"var sf=window.__spacefast||{};",
|
|
727
|
+
"var ev=sf.event||{};",
|
|
728
|
+
"return ev.detail||{};",
|
|
729
|
+
"})()",
|
|
730
|
+
].join("");
|
|
731
|
+
}
|
|
732
|
+
function providerBootstrapHtml(templateId, config) {
|
|
733
|
+
switch (templateId) {
|
|
734
|
+
case "google-analytics": {
|
|
735
|
+
const measurementId = templateFieldValue(config, "measurementId").toUpperCase();
|
|
736
|
+
return {
|
|
737
|
+
src: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(measurementId)}`,
|
|
738
|
+
attributes: { async: true },
|
|
739
|
+
html: htmlScript([
|
|
740
|
+
"window.dataLayer = window.dataLayer || [];",
|
|
741
|
+
"function gtag(){dataLayer.push(arguments);}",
|
|
742
|
+
"gtag('js', new Date());",
|
|
743
|
+
`gtag('config', ${JSON.stringify(measurementId)});`,
|
|
744
|
+
].join("\n")),
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
case "google-tag-manager": {
|
|
748
|
+
const containerId = templateFieldValue(config, "containerId").toUpperCase();
|
|
749
|
+
return {
|
|
750
|
+
html: htmlScript([
|
|
751
|
+
"(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':",
|
|
752
|
+
"new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],",
|
|
753
|
+
"j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=",
|
|
754
|
+
"'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);",
|
|
755
|
+
`})(window,document,'script','dataLayer',${JSON.stringify(containerId)});`,
|
|
756
|
+
].join("\n")),
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
case "meta-pixel": {
|
|
760
|
+
const pixelId = templateFieldValue(config, "pixelId");
|
|
761
|
+
return {
|
|
762
|
+
html: htmlScript([
|
|
763
|
+
"!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?",
|
|
764
|
+
"n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;",
|
|
765
|
+
"n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;",
|
|
766
|
+
"t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}",
|
|
767
|
+
"(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');",
|
|
768
|
+
`fbq('init', ${JSON.stringify(pixelId)});`,
|
|
769
|
+
"fbq('track', 'PageView');",
|
|
770
|
+
].join("\n")),
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
case "tiktok-pixel": {
|
|
774
|
+
const pixelId = templateFieldValue(config, "pixelId");
|
|
775
|
+
return {
|
|
776
|
+
html: htmlScript([
|
|
777
|
+
"!function (w, d, t) {",
|
|
778
|
+
"w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=['page','track','identify','instances','debug','on','off','once','ready','alias','group','enableCookie','disableCookie'];",
|
|
779
|
+
"ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};",
|
|
780
|
+
"for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);",
|
|
781
|
+
"ttq.instance=function(t){var e=ttq._i[t]||[];for(var n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e};",
|
|
782
|
+
"ttq.load=function(e,n){var i='https://analytics.tiktok.com/i18n/pixel/events.js';ttq._i=ttq._i||{};ttq._i[e]=[];ttq._i[e]._u=i;ttq._t=ttq._t||{};ttq._t[e]=+new Date;ttq._o=ttq._o||{};ttq._o[e]=n||{};var o=document.createElement('script');o.type='text/javascript';o.async=!0;o.src=i+'?sdkid='+e+'&lib='+t;var a=document.getElementsByTagName('script')[0];a.parentNode.insertBefore(o,a)};",
|
|
783
|
+
`ttq.load(${JSON.stringify(pixelId)});ttq.page();`,
|
|
784
|
+
"}(window, document, 'ttq');",
|
|
785
|
+
].join("\n")),
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
case "linkedin-insight": {
|
|
789
|
+
const partnerId = templateFieldValue(config, "partnerId");
|
|
790
|
+
return {
|
|
791
|
+
html: htmlScript([
|
|
792
|
+
"window._linkedin_partner_id = window._linkedin_partner_id || [];",
|
|
793
|
+
`window._linkedin_partner_id.push(${JSON.stringify(partnerId)});`,
|
|
794
|
+
"(function(l){if(!l){window.lintrk=function(a,b){window.lintrk.q.push([a,b])};window.lintrk.q=[]}",
|
|
795
|
+
"var s=document.getElementsByTagName('script')[0];var b=document.createElement('script');",
|
|
796
|
+
"b.type='text/javascript';b.async=true;b.src='https://snap.licdn.com/li.lms-analytics/insight.min.js';",
|
|
797
|
+
"s.parentNode.insertBefore(b,s);})(window.lintrk);",
|
|
798
|
+
].join("\n")),
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
case "posthog": {
|
|
802
|
+
const apiKey = templateFieldValue(config, "apiKey");
|
|
803
|
+
const host = templateFieldValue(config, "host") || "https://us.i.posthog.com";
|
|
804
|
+
return {
|
|
805
|
+
html: htmlScript([
|
|
806
|
+
"!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){",
|
|
807
|
+
"function g(t,e){var o=e.split('.');2==o.length&&(t=t[o[0]],e=o[1]);t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}",
|
|
808
|
+
"p=t.createElement('script');p.type='text/javascript';p.async=!0;p.src=s.api_host+'/static/array.js';",
|
|
809
|
+
"r=t.getElementsByTagName('script')[0];r.parentNode.insertBefore(p,r);",
|
|
810
|
+
"var u=e;void 0!==a?u=e[a]=[]:a='posthog';u.people=u.people||[];u.toString=function(t){var e='posthog';return'posthog'!==a&&(e+='.'+a),t||(e+=' (stub)'),e};",
|
|
811
|
+
"u.people.toString=function(){return u.toString(1)+'.people (stub)'};o='capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags reloadFeatureFlags getFeatureFlag getFeatureFlagPayload group'.split(' ');",
|
|
812
|
+
"for(n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);",
|
|
813
|
+
`posthog.init(${JSON.stringify(apiKey)}, { api_host: ${JSON.stringify(host)} });`,
|
|
814
|
+
].join("\n")),
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
case "plausible": {
|
|
818
|
+
const domain = templateFieldValue(config, "domain");
|
|
819
|
+
const scriptUrl = templateFieldValue(config, "scriptUrl") || "https://plausible.io/js/script.js";
|
|
820
|
+
return { src: scriptUrl, attributes: { async: true, defer: true, "data-domain": domain } };
|
|
821
|
+
}
|
|
822
|
+
case "amplitude": {
|
|
823
|
+
const apiKey = templateFieldValue(config, "apiKey");
|
|
824
|
+
return {
|
|
825
|
+
src: "https://cdn.amplitude.com/libs/analytics-browser-2-min.js.gz",
|
|
826
|
+
attributes: { async: true },
|
|
827
|
+
html: htmlScript(`window.amplitude && amplitude.init(${JSON.stringify(apiKey)});`),
|
|
828
|
+
htmlAfterLoad: true,
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
case "segment": {
|
|
832
|
+
const writeKey = templateFieldValue(config, "writeKey");
|
|
833
|
+
return {
|
|
834
|
+
html: htmlScript([
|
|
835
|
+
"!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)",
|
|
836
|
+
"if(analytics.invoked)window.console&&console.error&&console.error('Segment snippet included twice.');",
|
|
837
|
+
"else{analytics.invoked=!0;analytics.methods=['trackSubmit','trackClick','trackLink','trackForm','pageview','identify','reset','group','track','ready','alias','debug','page','screen','once','off','on','addSourceMiddleware','addIntegrationMiddleware','setAnonymousId','addDestinationMiddleware','register'];",
|
|
838
|
+
"analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};",
|
|
839
|
+
"for(var e=0;e<analytics.methods.length;e++){var key=analytics.methods[e];analytics[key]=analytics.factory(key)}",
|
|
840
|
+
"analytics.load=function(key,e){var t=document.createElement('script');t.type='text/javascript';t.async=!0;t.src='https://cdn.segment.com/analytics.js/v1/'+key+'/analytics.min.js';var n=document.getElementsByTagName('script')[0];n.parentNode.insertBefore(t,n);analytics._loadOptions=e};",
|
|
841
|
+
`analytics._writeKey=${JSON.stringify(writeKey)};analytics.SNIPPET_VERSION='5.2.0';analytics.load(${JSON.stringify(writeKey)});analytics.page();}}();`,
|
|
842
|
+
].join("\n")),
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
case "sentry-browser": {
|
|
846
|
+
const loaderKey = templateFieldValue(config, "loaderKey");
|
|
847
|
+
return {
|
|
848
|
+
src: `https://js.sentry-cdn.com/${encodeURIComponent(loaderKey)}.min.js`,
|
|
849
|
+
attributes: { crossorigin: "anonymous" },
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
case "intercom": {
|
|
853
|
+
const appId = templateFieldValue(config, "appId");
|
|
854
|
+
return {
|
|
855
|
+
html: htmlScript([
|
|
856
|
+
`window.intercomSettings = Object.assign({}, window.intercomSettings || {}, { app_id: ${JSON.stringify(appId)} });`,
|
|
857
|
+
"(function(){var w=window;var ic=w.Intercom;if(typeof ic==='function'){ic('reattach_activator');ic('update',w.intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/'+w.intercomSettings.app_id;var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();",
|
|
858
|
+
].join("\n")),
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
case "hubspot": {
|
|
862
|
+
const portalId = templateFieldValue(config, "portalId");
|
|
863
|
+
return {
|
|
864
|
+
src: `https://js.hs-scripts.com/${encodeURIComponent(portalId)}.js`,
|
|
865
|
+
attributes: { async: true, defer: true, id: "hs-script-loader" },
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
case "crisp": {
|
|
869
|
+
const websiteId = templateFieldValue(config, "websiteId");
|
|
870
|
+
return {
|
|
871
|
+
html: htmlScript([
|
|
872
|
+
"window.$crisp=[];",
|
|
873
|
+
`window.CRISP_WEBSITE_ID=${JSON.stringify(websiteId)};`,
|
|
874
|
+
"(function(){var d=document;var s=d.createElement('script');s.src='https://client.crisp.chat/l.js';s.async=1;d.getElementsByTagName('head')[0].appendChild(s);})();",
|
|
875
|
+
].join("\n")),
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
case "custom-javascript":
|
|
879
|
+
return { html: htmlScript(templateFieldValue(config, "code")) };
|
|
880
|
+
}
|
|
881
|
+
const exhaustive = templateId;
|
|
882
|
+
return exhaustive;
|
|
883
|
+
}
|
|
884
|
+
function providerEventHtml(templateId, templateName, config) {
|
|
885
|
+
const nameExpr = eventNameExpression(templateName);
|
|
886
|
+
const detailExpr = eventDetailExpression();
|
|
887
|
+
switch (templateId) {
|
|
888
|
+
case "google-analytics":
|
|
889
|
+
return htmlScript(`window.gtag && gtag('event', ${nameExpr}, ${detailExpr});`);
|
|
890
|
+
case "google-tag-manager":
|
|
891
|
+
return htmlScript(`window.dataLayer && dataLayer.push(Object.assign({ event: ${nameExpr} }, ${detailExpr}));`);
|
|
892
|
+
case "meta-pixel":
|
|
893
|
+
return htmlScript(`window.fbq && fbq('trackCustom', ${nameExpr}, ${detailExpr});`);
|
|
894
|
+
case "tiktok-pixel":
|
|
895
|
+
return htmlScript(`window.ttq && ttq.track(${nameExpr}, ${detailExpr});`);
|
|
896
|
+
case "linkedin-insight": {
|
|
897
|
+
const conversionId = templateFieldValue(config, "conversionId");
|
|
898
|
+
return conversionId
|
|
899
|
+
? htmlScript(`window.lintrk && lintrk('track', { conversion_id: ${JSON.stringify(conversionId)} });`)
|
|
900
|
+
: "";
|
|
901
|
+
}
|
|
902
|
+
case "posthog":
|
|
903
|
+
return htmlScript(`window.posthog && posthog.capture(${nameExpr}, ${detailExpr});`);
|
|
904
|
+
case "plausible":
|
|
905
|
+
return htmlScript(`window.plausible && plausible(${nameExpr}, { props: ${detailExpr} });`);
|
|
906
|
+
case "amplitude":
|
|
907
|
+
return htmlScript(`window.amplitude && amplitude.track && amplitude.track(${nameExpr}, ${detailExpr});`);
|
|
908
|
+
case "segment":
|
|
909
|
+
return htmlScript(`window.analytics && analytics.track && analytics.track(${nameExpr}, ${detailExpr});`);
|
|
910
|
+
case "intercom":
|
|
911
|
+
return htmlScript(`window.Intercom && Intercom('trackEvent', ${nameExpr}, ${detailExpr});`);
|
|
912
|
+
case "hubspot":
|
|
913
|
+
return htmlScript(`window._hsq=window._hsq||[];_hsq.push(['trackEvent', { id: ${nameExpr}, value: JSON.stringify(${detailExpr}) }]);`);
|
|
914
|
+
case "crisp":
|
|
915
|
+
return htmlScript(`window.$crisp && $crisp.push(['set', 'session:event', [[${nameExpr}, ${detailExpr}]]]);`);
|
|
916
|
+
case "sentry-browser":
|
|
917
|
+
return "";
|
|
918
|
+
case "custom-javascript":
|
|
919
|
+
return null;
|
|
920
|
+
}
|
|
921
|
+
return null;
|
|
922
|
+
}
|
|
923
|
+
function templatePrimaryValue(template, config) {
|
|
924
|
+
const field = template.fields.find((item) => item.required) ?? template.fields[0];
|
|
925
|
+
return field ? templateFieldValue(config, field.key) : "";
|
|
926
|
+
}
|
|
927
|
+
function validateTemplateSelection(selection) {
|
|
928
|
+
const template = tagTemplateById(selection.templateId);
|
|
929
|
+
if (!template) {
|
|
930
|
+
throw new Error(`Unknown tag template: ${selection.templateId}`);
|
|
931
|
+
}
|
|
932
|
+
for (const field of template.fields) {
|
|
933
|
+
if (field.required && !templateFieldValue(selection.config, field.key)) {
|
|
934
|
+
throw new Error(`${template.name} requires ${field.label}.`);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
return template;
|
|
938
|
+
}
|
|
939
|
+
export function tagPresetTriggers(ids) {
|
|
940
|
+
const triggerIds = new Set(ids);
|
|
941
|
+
return TAG_TRIGGER_PRESETS.filter((preset) => triggerIds.has(preset.id)).map((preset) => ({
|
|
942
|
+
id: preset.triggerId,
|
|
943
|
+
type: preset.id,
|
|
944
|
+
source: "preset",
|
|
945
|
+
}));
|
|
946
|
+
}
|
|
947
|
+
export function tagGraphFromTemplateSelection(input) {
|
|
948
|
+
const selection = tagTemplateSelectionSchema.parse(input);
|
|
949
|
+
const template = validateTemplateSelection(selection);
|
|
950
|
+
const triggers = selection.triggers?.length ? selection.triggers : template.defaultTriggers;
|
|
951
|
+
const triggerIds = triggers
|
|
952
|
+
.map((trigger) => TAG_TRIGGER_PRESETS.find((preset) => preset.id === trigger)?.triggerId)
|
|
953
|
+
.filter((triggerId) => Boolean(triggerId));
|
|
954
|
+
const primary = templatePrimaryValue(template, selection.config);
|
|
955
|
+
const idBase = selection.id ?? `tag.${template.id}.${safeTagIdPart(primary || template.id)}`;
|
|
956
|
+
const consent = selection.consentCategories ?? template.consentCategories;
|
|
957
|
+
const common = {
|
|
958
|
+
source: "template",
|
|
959
|
+
templateId: template.id,
|
|
960
|
+
enabled: selection.enabled,
|
|
961
|
+
consent: { categories: consent },
|
|
962
|
+
environments: selection.environments,
|
|
963
|
+
schedule: selection.schedule,
|
|
964
|
+
};
|
|
965
|
+
const bootstrap = providerBootstrapHtml(template.id, selection.config);
|
|
966
|
+
const tags = [
|
|
967
|
+
{
|
|
968
|
+
...common,
|
|
969
|
+
id: idBase,
|
|
970
|
+
name: selection.name ?? template.name,
|
|
971
|
+
triggerIds: template.id === "custom-javascript"
|
|
972
|
+
? triggerIds
|
|
973
|
+
: triggerIds.length > 0
|
|
974
|
+
? [triggerIds[0]]
|
|
975
|
+
: [],
|
|
976
|
+
once: template.id !== "custom-javascript",
|
|
977
|
+
...bootstrap,
|
|
978
|
+
},
|
|
979
|
+
];
|
|
980
|
+
for (const trigger of triggers.filter((item) => item !== "page_view")) {
|
|
981
|
+
const triggerId = TAG_TRIGGER_PRESETS.find((preset) => preset.id === trigger)?.triggerId;
|
|
982
|
+
const html = providerEventHtml(template.id, `${template.name} ${trigger.replace(/_/g, " ")}`, selection.config);
|
|
983
|
+
if (!triggerId || !html)
|
|
984
|
+
continue;
|
|
985
|
+
tags.push({
|
|
986
|
+
...common,
|
|
987
|
+
id: `${idBase}.${trigger}`,
|
|
988
|
+
name: `${selection.name ?? template.name} ${trigger.replace(/_/g, " ")}`,
|
|
989
|
+
triggerIds: [triggerId],
|
|
990
|
+
dependsOnTagId: idBase,
|
|
991
|
+
html,
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
return {
|
|
995
|
+
...emptyTagGraph,
|
|
996
|
+
tags,
|
|
997
|
+
triggers: tagPresetTriggers(triggers),
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
export function mergeTagGraphs(...graphs) {
|
|
1001
|
+
const tagMap = new Map();
|
|
1002
|
+
const triggerMap = new Map();
|
|
1003
|
+
const variableMap = new Map();
|
|
1004
|
+
const systemModules = {};
|
|
1005
|
+
const consentPolicies = [];
|
|
1006
|
+
for (const graph of graphs) {
|
|
1007
|
+
if (!graph)
|
|
1008
|
+
continue;
|
|
1009
|
+
for (const tag of graph.tags ?? []) {
|
|
1010
|
+
const id = typeof tag.id === "string" ? tag.id : JSON.stringify(tag);
|
|
1011
|
+
tagMap.set(id, tag);
|
|
1012
|
+
}
|
|
1013
|
+
for (const trigger of graph.triggers ?? []) {
|
|
1014
|
+
const id = typeof trigger.id === "string" ? trigger.id : JSON.stringify(trigger);
|
|
1015
|
+
triggerMap.set(id, trigger);
|
|
1016
|
+
}
|
|
1017
|
+
for (const variable of graph.variables ?? []) {
|
|
1018
|
+
const id = typeof variable.id === "string" ? variable.id : JSON.stringify(variable);
|
|
1019
|
+
variableMap.set(id, variable);
|
|
1020
|
+
}
|
|
1021
|
+
Object.assign(systemModules, graph.systemModules ?? {});
|
|
1022
|
+
const consentPolicy = graph.consentPolicy;
|
|
1023
|
+
if (consentPolicy)
|
|
1024
|
+
consentPolicies.push(consentPolicy);
|
|
1025
|
+
}
|
|
1026
|
+
const consentPolicy = mergeTagConsentPolicyInputs(...consentPolicies);
|
|
1027
|
+
return {
|
|
1028
|
+
format: "spacefast.tag_graph.v1",
|
|
1029
|
+
tags: [...tagMap.values()],
|
|
1030
|
+
triggers: [...triggerMap.values()],
|
|
1031
|
+
variables: [...variableMap.values()],
|
|
1032
|
+
systemModules,
|
|
1033
|
+
...(consentPolicy ? { consentPolicy } : {}),
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
export function tagGraphFromTemplateSelections(selections) {
|
|
1037
|
+
return mergeTagGraphs(...selections.map((selection) => tagGraphFromTemplateSelection(selection)));
|
|
1038
|
+
}
|
|
1039
|
+
export const tagEffectiveResponseSchema = dataEnvelope(z.object({
|
|
1040
|
+
tagSetId: z.string().nullable(),
|
|
1041
|
+
environment: tagEnvironmentSchema,
|
|
1042
|
+
versionId: z.string().nullable(),
|
|
1043
|
+
graph: tagGraphSchema,
|
|
1044
|
+
graphRevision: z.number().int().nonnegative(),
|
|
1045
|
+
sdkRevision: z.string().nullable(),
|
|
1046
|
+
sources: z.array(z.object({
|
|
1047
|
+
type: z.enum(["team", "space", "system"]),
|
|
1048
|
+
versionId: z.string().nullable(),
|
|
1049
|
+
})),
|
|
1050
|
+
}));
|