@walkeros/server-destination-datamanager 0.3.1 → 0.4.0
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/dev.d.mts +165 -0
- package/dist/dev.d.ts +165 -0
- package/dist/dev.js +1 -0
- package/dist/dev.js.map +1 -0
- package/dist/dev.mjs +1 -0
- package/dist/dev.mjs.map +1 -0
- package/dist/index.d.mts +34 -111
- package/dist/index.d.ts +34 -111
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/schemas.d.mts +1 -1
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.js +1 -1
- package/dist/schemas.js.map +1 -1
- package/dist/schemas.mjs +1 -1
- package/dist/schemas.mjs.map +1 -1
- package/package.json +7 -7
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/push.ts","../src/format.ts","../src/hash.ts","../src/utils.ts","../src/types/index.ts","../src/examples/index.ts","../src/examples/mapping.ts","../src/examples/basic.ts","../src/schemas.ts","../src/schemas/primitives.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, Settings, PartialConfig } from './types';\nimport { throwError } from '@walkeros/core';\n\nexport function getConfig(partialConfig: PartialConfig = {}): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { accessToken, destinations } = settings;\n\n if (!accessToken) throwError('Config settings accessToken missing');\n if (!destinations || destinations.length === 0)\n throwError('Config settings destinations missing or empty');\n\n const settingsConfig: Settings = {\n ...settings,\n accessToken,\n destinations,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { PushFn } from './types';\nimport type { IngestEventsRequest, IngestEventsResponse } from './types';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { formatEvent, formatConsent } from './format';\nimport { createLogger } from './utils';\n\nexport const push: PushFn = async function (\n event,\n { config, mapping, data, collector, env },\n) {\n const {\n accessToken,\n destinations,\n eventSource,\n validateOnly = false,\n url = 'https://datamanager.googleapis.com/v1',\n consent: requestConsent,\n testEventCode,\n logLevel = 'none',\n userData,\n userId,\n clientId,\n sessionAttributes,\n consentAdUserData,\n consentAdPersonalization,\n } = config.settings!;\n\n const logger = createLogger(logLevel);\n\n // Extract Settings guided helpers\n const userDataMapped = userData\n ? await getMappingValue(event, { map: userData })\n : {};\n const userIdMapped = userId\n ? await getMappingValue(event, userId)\n : undefined;\n const clientIdMapped = clientId\n ? await getMappingValue(event, clientId)\n : undefined;\n const sessionAttributesMapped = sessionAttributes\n ? await getMappingValue(event, sessionAttributes)\n : undefined;\n\n // Extract consent from Settings\n const consentAdUserDataValue =\n typeof consentAdUserData === 'boolean'\n ? consentAdUserData\n : typeof consentAdUserData === 'string' && event.consent\n ? event.consent[consentAdUserData]\n : undefined;\n\n const consentAdPersonalizationValue =\n typeof consentAdPersonalization === 'boolean'\n ? consentAdPersonalization\n : typeof consentAdPersonalization === 'string' && event.consent\n ? event.consent[consentAdPersonalization]\n : undefined;\n\n // Build Settings helpers object\n const settingsHelpers: Record<string, unknown> = {};\n if (isObject(userDataMapped)) {\n Object.assign(settingsHelpers, userDataMapped);\n }\n if (userIdMapped !== undefined) settingsHelpers.userId = userIdMapped;\n if (clientIdMapped !== undefined) settingsHelpers.clientId = clientIdMapped;\n if (sessionAttributesMapped !== undefined)\n settingsHelpers.sessionAttributes = sessionAttributesMapped;\n if (consentAdUserDataValue !== undefined)\n settingsHelpers.adUserData = consentAdUserDataValue;\n if (consentAdPersonalizationValue !== undefined)\n settingsHelpers.adPersonalization = consentAdPersonalizationValue;\n\n // Get mapped data from destination config and event mapping\n const configData = config.data\n ? await getMappingValue(event, config.data)\n : {};\n const eventData = isObject(data) ? data : {};\n\n // Merge: Settings helpers < config.data < event mapping data\n const finalData = {\n ...settingsHelpers,\n ...(isObject(configData) ? configData : {}),\n ...eventData,\n };\n\n // Format event for Data Manager API\n const dataManagerEvent = await formatEvent(event, finalData);\n\n logger.debug('Processing event', {\n name: event.name,\n id: event.id,\n timestamp: event.timestamp,\n });\n\n // Apply event source from settings if not set\n if (!dataManagerEvent.eventSource && eventSource) {\n dataManagerEvent.eventSource = eventSource;\n }\n\n // Apply request-level consent if event doesn't have consent\n if (!dataManagerEvent.consent && requestConsent) {\n dataManagerEvent.consent = requestConsent;\n }\n\n // Build API request\n const requestBody: IngestEventsRequest = {\n events: [dataManagerEvent],\n destinations,\n };\n\n // Add optional parameters\n if (requestConsent) {\n requestBody.consent = requestConsent;\n }\n\n if (validateOnly) {\n requestBody.validateOnly = true;\n }\n\n if (testEventCode) {\n requestBody.testEventCode = testEventCode;\n }\n\n // Send to Data Manager API\n const fetchFn = env?.fetch || fetch;\n const endpoint = `${url}/events:ingest`;\n\n logger.debug('Sending to Data Manager API', {\n endpoint,\n eventCount: requestBody.events.length,\n destinations: destinations.length,\n validateOnly,\n });\n\n const response = await fetchFn(endpoint, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n logger.error('API request failed', {\n status: response.status,\n error: errorText,\n });\n throw new Error(\n `Data Manager API error (${response.status}): ${errorText}`,\n );\n }\n\n const result: IngestEventsResponse = await response.json();\n\n logger.debug('API response', {\n status: response.status,\n requestId: result.requestId,\n });\n\n // If validation errors exist, throw them\n if (result.validationErrors && result.validationErrors.length > 0) {\n logger.error('Validation errors', {\n errors: result.validationErrors,\n });\n throw new Error(\n `Validation errors: ${JSON.stringify(result.validationErrors)}`,\n );\n }\n\n logger.info('Event processed successfully', {\n requestId: result.requestId,\n });\n};\n","import type { WalkerOS } from '@walkeros/core';\nimport { isString, isDefined } from '@walkeros/core';\nimport type {\n Event,\n UserData,\n UserIdentifier,\n AdIdentifiers,\n Consent,\n ConsentStatus,\n} from './types';\nimport { hashEmail, hashPhone, hashName } from './hash';\n\n/**\n * Format walkerOS event timestamp to RFC 3339 format\n * https://developers.google.com/data-manager/api/reference/rest/v1/Event\n *\n * walkerOS timestamp is in milliseconds, RFC 3339 format: \"2024-01-15T10:30:00Z\"\n */\nexport function formatTimestamp(timestamp: number): string {\n return new Date(timestamp).toISOString();\n}\n\n/**\n * Format user identifiers from mapped data\n * https://developers.google.com/data-manager/api/reference/rest/v1/UserData\n *\n * User data must be explicitly mapped in the mapping configuration.\n * Max 10 identifiers per event\n */\nexport async function formatUserData(\n data: Record<string, unknown>,\n): Promise<UserData | undefined> {\n const identifiers: UserIdentifier[] = [];\n\n // Extract from mapped data only\n // Email\n if (isString(data.email) && data.email) {\n const hashedEmail = await hashEmail(data.email);\n if (hashedEmail) {\n identifiers.push({ emailAddress: hashedEmail });\n }\n }\n\n // Phone\n if (isString(data.phone) && data.phone) {\n const hashedPhone = await hashPhone(data.phone);\n if (hashedPhone) {\n identifiers.push({ phoneNumber: hashedPhone });\n }\n }\n\n // Address from mapped properties\n const hasAddress =\n data.firstName || data.lastName || data.regionCode || data.postalCode;\n\n if (hasAddress) {\n const address: Record<string, string> = {};\n\n if (isString(data.firstName) && data.firstName) {\n address.givenName = await hashName(data.firstName, 'given');\n }\n\n if (isString(data.lastName) && data.lastName) {\n address.familyName = await hashName(data.lastName, 'family');\n }\n\n // Region code is NOT hashed\n if (isString(data.regionCode) && data.regionCode) {\n address.regionCode = data.regionCode.toUpperCase();\n }\n\n // Postal code is NOT hashed\n if (isString(data.postalCode) && data.postalCode) {\n address.postalCode = data.postalCode;\n }\n\n if (Object.keys(address).length > 0) {\n identifiers.push({ address });\n }\n }\n\n // Limit to 10 identifiers\n if (identifiers.length === 0) return undefined;\n\n return {\n userIdentifiers: identifiers.slice(0, 10),\n };\n}\n\n/**\n * Extract and format attribution identifiers from mapped data\n * https://developers.google.com/data-manager/api/reference/rest/v1/AdIdentifiers\n *\n * Attribution identifiers should be mapped explicitly in the mapping configuration.\n * Example: { gclid: 'context.gclid', gbraid: 'context.gbraid' }\n */\nexport function formatAdIdentifiers(\n data: Record<string, unknown>,\n): AdIdentifiers | undefined {\n const identifiers: AdIdentifiers = {};\n\n // Extract from mapped data (already processed by mapping system)\n if (isString(data.gclid) && data.gclid) {\n identifiers.gclid = data.gclid;\n }\n if (isString(data.gbraid) && data.gbraid) {\n identifiers.gbraid = data.gbraid;\n }\n if (isString(data.wbraid) && data.wbraid) {\n identifiers.wbraid = data.wbraid;\n }\n if (isString(data.sessionAttributes) && data.sessionAttributes) {\n identifiers.sessionAttributes = data.sessionAttributes;\n }\n\n return Object.keys(identifiers).length > 0 ? identifiers : undefined;\n}\n\n/**\n * Map walkerOS consent to Data Manager consent format\n * https://developers.google.com/data-manager/api/devguides/concepts/dma\n *\n * walkerOS: { marketing: true, personalization: false }\n * Data Manager: { adUserData: 'CONSENT_GRANTED', adPersonalization: 'CONSENT_DENIED' }\n */\nexport function formatConsent(\n walkerOSConsent: WalkerOS.Consent | undefined,\n): Consent | undefined {\n if (!walkerOSConsent) return undefined;\n\n const consent: Consent = {};\n\n // Map marketing consent to adUserData\n if (isDefined(walkerOSConsent.marketing)) {\n consent.adUserData = walkerOSConsent.marketing\n ? 'CONSENT_GRANTED'\n : 'CONSENT_DENIED';\n }\n\n // Map personalization consent to adPersonalization\n if (isDefined(walkerOSConsent.personalization)) {\n consent.adPersonalization = walkerOSConsent.personalization\n ? 'CONSENT_GRANTED'\n : 'CONSENT_DENIED';\n }\n\n return Object.keys(consent).length > 0 ? consent : undefined;\n}\n\n/**\n * Format complete event for Data Manager API\n * https://developers.google.com/data-manager/api/reference/rest/v1/Event\n */\nexport async function formatEvent(\n event: WalkerOS.Event,\n mappedData?: Record<string, unknown>,\n): Promise<Event> {\n const dataManagerEvent: Event = {\n eventTimestamp: formatTimestamp(event.timestamp),\n };\n\n // Use only mapped data (no fallback to event.data)\n const data = mappedData || {};\n\n // Transaction ID for deduplication\n if (isString(data.transactionId) && data.transactionId) {\n dataManagerEvent.transactionId = data.transactionId.substring(0, 512);\n }\n\n // Client ID (GA)\n if (isString(data.clientId) && data.clientId) {\n dataManagerEvent.clientId = data.clientId.substring(0, 255);\n }\n\n // User ID\n if (isString(data.userId) && data.userId) {\n dataManagerEvent.userId = data.userId.substring(0, 256);\n }\n\n // User data\n const userData = await formatUserData(data);\n if (userData) {\n dataManagerEvent.userData = userData;\n }\n\n // Attribution identifiers\n const adIdentifiers = formatAdIdentifiers(data);\n if (adIdentifiers) {\n dataManagerEvent.adIdentifiers = adIdentifiers;\n }\n\n // Conversion value\n if (typeof data.conversionValue === 'number') {\n dataManagerEvent.conversionValue = data.conversionValue;\n }\n\n // Currency\n if (isString(data.currency) && data.currency) {\n dataManagerEvent.currency = data.currency.substring(0, 3).toUpperCase();\n }\n\n // Cart data\n if (data.cartData && typeof data.cartData === 'object') {\n dataManagerEvent.cartData = data.cartData as Event['cartData'];\n }\n\n // Event name (for GA4)\n if (isString(data.eventName) && data.eventName) {\n dataManagerEvent.eventName = data.eventName.substring(0, 40);\n }\n\n // Event source\n if (isString(data.eventSource) && data.eventSource) {\n dataManagerEvent.eventSource = data.eventSource as Event['eventSource'];\n }\n\n // Consent - check mapped data first, then fallback to event.consent\n const mappedConsent: Consent = {};\n\n // Check for mapped consent values (from Settings or event mapping)\n if (typeof data.adUserData === 'boolean') {\n mappedConsent.adUserData = data.adUserData\n ? 'CONSENT_GRANTED'\n : 'CONSENT_DENIED';\n }\n if (typeof data.adPersonalization === 'boolean') {\n mappedConsent.adPersonalization = data.adPersonalization\n ? 'CONSENT_GRANTED'\n : 'CONSENT_DENIED';\n }\n\n // If no mapped consent, fall back to event.consent\n if (Object.keys(mappedConsent).length === 0) {\n const eventConsent = formatConsent(event.consent);\n if (eventConsent) {\n dataManagerEvent.consent = eventConsent;\n }\n } else {\n dataManagerEvent.consent = mappedConsent;\n }\n\n return dataManagerEvent;\n}\n","import { isString } from '@walkeros/core';\nimport { getHashServer } from '@walkeros/server-core';\n\n/**\n * Normalize email address according to Google Data Manager requirements\n * https://developers.google.com/data-manager/api/devguides/concepts/formatting#email\n *\n * 1. Trim whitespace\n * 2. Convert to lowercase\n * 3. Remove dots (.) for gmail.com and googlemail.com\n * 4. SHA-256 hash\n */\nexport async function hashEmail(email: string): Promise<string> {\n if (!isString(email) || !email) return '';\n\n // Trim and lowercase\n let normalized = email.trim().toLowerCase();\n\n // Remove dots for Gmail addresses\n if (\n normalized.endsWith('@gmail.com') ||\n normalized.endsWith('@googlemail.com')\n ) {\n const [localPart, domain] = normalized.split('@');\n normalized = `${localPart.replace(/\\./g, '')}@${domain}`;\n }\n\n return getHashServer(normalized);\n}\n\n/**\n * Normalize phone number to E.164 format and hash\n * https://developers.google.com/data-manager/api/devguides/concepts/formatting#phone\n *\n * E.164 format: +[country code][number] (max 15 digits after +)\n * Example: +18005550100\n *\n * 1. Remove all non-digit characters except leading +\n * 2. Ensure it starts with +\n * 3. SHA-256 hash\n */\nexport async function hashPhone(phone: string): Promise<string> {\n if (!isString(phone) || !phone) return '';\n\n // Remove all non-digit characters except + at the start\n let normalized = phone.trim();\n\n // Extract country code if present\n const hasPlus = normalized.startsWith('+');\n\n // Remove all non-digits\n normalized = normalized.replace(/\\D/g, '');\n\n // Add + prefix if it was there or if number is long enough\n if (hasPlus || normalized.length > 10) {\n normalized = `+${normalized}`;\n } else {\n // Assume US number if no country code (default behavior)\n normalized = `+1${normalized}`;\n }\n\n return getHashServer(normalized);\n}\n\n/**\n * Normalize and hash a name (first or last name)\n * https://developers.google.com/data-manager/api/devguides/concepts/formatting#name\n *\n * 1. Trim whitespace\n * 2. Convert to lowercase\n * 3. Remove common prefixes (Mr., Mrs., Dr.) for first names\n * 4. Remove common suffixes (Jr., Sr., III) for last names\n * 5. SHA-256 hash\n */\nexport async function hashName(\n name: string,\n type: 'given' | 'family' = 'given',\n): Promise<string> {\n if (!isString(name) || !name) return '';\n\n // Trim and lowercase\n let normalized = name.trim().toLowerCase();\n\n // Remove prefixes for given names\n if (type === 'given') {\n const prefixes = ['mr.', 'mrs.', 'ms.', 'miss.', 'dr.', 'prof.'];\n for (const prefix of prefixes) {\n if (normalized.startsWith(prefix)) {\n normalized = normalized.substring(prefix.length).trim();\n break;\n }\n }\n }\n\n // Remove suffixes for family names (check with and without space)\n // Sort by length (longest first) to match \"iii\" before \"ii\"\n if (type === 'family') {\n const suffixes = ['jr.', 'sr.', 'iii', 'ii', 'iv', 'v'];\n for (const suffix of suffixes) {\n // Check for suffix with space before it (e.g., \" jr.\")\n const suffixWithSpace = ` ${suffix}`;\n if (normalized.endsWith(suffixWithSpace)) {\n normalized = normalized\n .substring(0, normalized.length - suffixWithSpace.length)\n .trim();\n break;\n }\n // Check for suffix without space\n if (normalized.endsWith(suffix)) {\n normalized = normalized\n .substring(0, normalized.length - suffix.length)\n .trim();\n break;\n }\n }\n }\n\n return getHashServer(normalized);\n}\n\n/**\n * Hash multiple email addresses\n */\nexport async function hashEmails(emails: string[]): Promise<string[]> {\n return Promise.all(emails.map((email) => hashEmail(email)));\n}\n\n/**\n * Hash multiple phone numbers\n */\nexport async function hashPhones(phones: string[]): Promise<string[]> {\n return Promise.all(phones.map((phone) => hashPhone(phone)));\n}\n","export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';\n\n/* eslint-disable no-console */\nexport function createLogger(level: LogLevel = 'none') {\n const levels = { debug: 0, info: 1, warn: 2, error: 3, none: 4 };\n const currentLevel = levels[level];\n\n return {\n debug: (message: string, data?: unknown) => {\n if (currentLevel <= 0)\n console.log(`[DataManager] ${message}`, data || '');\n },\n info: (message: string, data?: unknown) => {\n if (currentLevel <= 1)\n console.log(`[DataManager] ${message}`, data || '');\n },\n warn: (message: string, data?: unknown) => {\n if (currentLevel <= 2)\n console.warn(`[DataManager] ${message}`, data || '');\n },\n error: (message: string, data?: unknown) => {\n if (currentLevel <= 3)\n console.error(`[DataManager] ${message}`, data || '');\n },\n };\n}\n/* eslint-enable no-console */\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\nimport type { LogLevel } from '../utils';\n\nexport interface Settings {\n /** OAuth 2.0 access token with datamanager scope */\n accessToken: string;\n\n /** Array of destination accounts and conversion actions/user lists */\n destinations: Destination[];\n\n /** Default event source if not specified per event */\n eventSource?: EventSource;\n\n /** Maximum number of events to batch before sending (max 2000) */\n batchSize?: number;\n\n /** Time in milliseconds to wait before auto-flushing batch */\n batchInterval?: number;\n\n /** If true, validate request without ingestion (testing mode) */\n validateOnly?: boolean;\n\n /** Override API endpoint (for testing) */\n url?: string;\n\n /** Request-level consent for all events */\n consent?: Consent;\n\n /** Test event code for debugging (optional) */\n testEventCode?: string;\n\n /** Log level for debugging (optional) */\n logLevel?: LogLevel;\n\n /** Guided helpers: User data mapping (applies to all events) */\n userData?: WalkerOSMapping.Map;\n\n /** Guided helper: First-party user ID */\n userId?: WalkerOSMapping.Value;\n\n /** Guided helper: GA4 client ID */\n clientId?: WalkerOSMapping.Value;\n\n /** Guided helper: Privacy-safe attribution (Google's sessionAttributes) */\n sessionAttributes?: WalkerOSMapping.Value;\n\n /** Consent mapping: Map consent field to adUserData (string = field name, boolean = static value) */\n consentAdUserData?: string | boolean;\n\n /** Consent mapping: Map consent field to adPersonalization (string = field name, boolean = static value) */\n consentAdPersonalization?: string | boolean;\n}\n\nexport interface Mapping {\n // Attribution identifiers (optional, for explicit mapping)\n gclid?: WalkerOSMapping.Value;\n gbraid?: WalkerOSMapping.Value;\n wbraid?: WalkerOSMapping.Value;\n sessionAttributes?: WalkerOSMapping.Value;\n}\n\nexport interface Env extends DestinationServer.Env {\n fetch?: typeof fetch;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env>;\n\nexport interface DestinationInterface\n extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n// Google Data Manager API Types\n// https://developers.google.com/data-manager/api/reference\n\n/**\n * Destination account and product identifier\n * https://developers.google.com/data-manager/api/reference/rest/v1/Destination\n */\nexport interface Destination {\n /** Operating account details */\n operatingAccount: OperatingAccount;\n\n /** Product-specific destination ID (conversion action or user list) */\n productDestinationId: string;\n}\n\n/**\n * Operating account information\n */\nexport interface OperatingAccount {\n /** Account ID (e.g., \"123-456-7890\" for Google Ads) */\n accountId: string;\n\n /** Type of account */\n accountType: AccountType;\n}\n\nexport type AccountType =\n | 'GOOGLE_ADS'\n | 'DISPLAY_VIDEO_ADVERTISER'\n | 'DISPLAY_VIDEO_PARTNER'\n | 'GOOGLE_ANALYTICS_PROPERTY';\n\nexport type EventSource = 'WEB' | 'APP' | 'IN_STORE' | 'PHONE' | 'OTHER';\n\n/**\n * Consent for Digital Markets Act (DMA) compliance\n * https://developers.google.com/data-manager/api/devguides/concepts/dma\n */\nexport interface Consent {\n /** Consent for data collection and use */\n adUserData?: ConsentStatus;\n\n /** Consent for ad personalization */\n adPersonalization?: ConsentStatus;\n}\n\nexport type ConsentStatus = 'CONSENT_GRANTED' | 'CONSENT_DENIED';\n\n/**\n * Request body for events.ingest API\n * https://developers.google.com/data-manager/api/reference/rest/v1/events/ingest\n */\nexport interface IngestEventsRequest {\n /** OAuth 2.0 access token */\n access_token?: string;\n\n /** Array of events to ingest (max 2000) */\n events: Event[];\n\n /** Array of destinations for these events (max 10) */\n destinations: Destination[];\n\n /** Request-level consent (overridden by event-level) */\n consent?: Consent;\n\n /** If true, validate without ingestion */\n validateOnly?: boolean;\n\n /** Test event code for debugging */\n testEventCode?: string;\n}\n\n/**\n * Single event for ingestion\n * https://developers.google.com/data-manager/api/reference/rest/v1/Event\n */\nexport interface Event {\n /** Event timestamp in RFC 3339 format */\n eventTimestamp: string;\n\n /** Transaction ID for deduplication (max 512 chars) */\n transactionId?: string;\n\n /** Google Analytics client ID (max 255 chars) */\n clientId?: string;\n\n /** First-party user ID (max 256 chars) */\n userId?: string;\n\n /** User data with identifiers (max 10 identifiers) */\n userData?: UserData;\n\n /** Attribution identifiers */\n adIdentifiers?: AdIdentifiers;\n\n /** Conversion value */\n conversionValue?: number;\n\n /** Currency code (ISO 4217, 3 chars) */\n currency?: string;\n\n /** Shopping cart data */\n cartData?: CartData;\n\n /** Event name for GA4 (max 40 chars, required for GA4) */\n eventName?: string;\n\n /** Source of the event */\n eventSource?: EventSource;\n\n /** Event-level consent (overrides request-level) */\n consent?: Consent;\n}\n\n/**\n * User data with identifiers\n * https://developers.google.com/data-manager/api/reference/rest/v1/UserData\n */\nexport interface UserData {\n /** Array of user identifiers (max 10) */\n userIdentifiers: UserIdentifier[];\n}\n\n/**\n * User identifier (email, phone, or address)\n */\nexport type UserIdentifier =\n | { emailAddress: string }\n | { phoneNumber: string }\n | { address: Address };\n\n/**\n * Address for user identification\n * https://developers.google.com/data-manager/api/reference/rest/v1/Address\n */\nexport interface Address {\n /** Given name (first name) - SHA-256 hashed */\n givenName?: string;\n\n /** Family name (last name) - SHA-256 hashed */\n familyName?: string;\n\n /** ISO-3166-1 alpha-2 country code - NOT hashed (e.g., \"US\", \"GB\") */\n regionCode?: string;\n\n /** Postal code - NOT hashed */\n postalCode?: string;\n}\n\n/**\n * Attribution identifiers\n * https://developers.google.com/data-manager/api/reference/rest/v1/AdIdentifiers\n */\nexport interface AdIdentifiers {\n /** Google Click ID (primary attribution) */\n gclid?: string;\n\n /** iOS attribution identifier (post-ATT) */\n gbraid?: string;\n\n /** Web-to-app attribution identifier */\n wbraid?: string;\n\n /** Session attributes (privacy-safe attribution) */\n sessionAttributes?: string;\n}\n\n/**\n * Shopping cart data\n * https://developers.google.com/data-manager/api/reference/rest/v1/CartData\n */\nexport interface CartData {\n /** Array of cart items (max 200) */\n items: CartItem[];\n}\n\n/**\n * Single cart item\n * https://developers.google.com/data-manager/api/reference/rest/v1/CartItem\n */\nexport interface CartItem {\n /** Merchant product ID (max 127 chars) */\n merchantProductId?: string;\n\n /** Item price */\n price?: number;\n\n /** Item quantity */\n quantity?: number;\n}\n\n/**\n * Response from events.ingest API\n * https://developers.google.com/data-manager/api/reference/rest/v1/IngestEventsResponse\n */\nexport interface IngestEventsResponse {\n /** Unique request ID for status checking */\n requestId: string;\n\n /** Validation errors (only if validateOnly=true) */\n validationErrors?: ValidationError[];\n}\n\n/**\n * Validation error\n */\nexport interface ValidationError {\n /** Error code */\n code: string;\n\n /** Human-readable error message */\n message: string;\n\n /** Field path that caused the error */\n fieldPath?: string;\n}\n\n/**\n * Request status response\n * https://developers.google.com/data-manager/api/reference/rest/v1/requestStatus/retrieve\n */\nexport interface RequestStatusResponse {\n /** Unique request ID */\n requestId: string;\n\n /** Processing state */\n state: RequestState;\n\n /** Number of events successfully ingested */\n eventsIngested?: number;\n\n /** Number of events that failed */\n eventsFailed?: number;\n\n /** Array of errors (if any) */\n errors?: RequestError[];\n}\n\nexport type RequestState =\n | 'STATE_UNSPECIFIED'\n | 'PENDING'\n | 'PROCESSING'\n | 'SUCCEEDED'\n | 'FAILED'\n | 'PARTIALLY_SUCCEEDED';\n\n/**\n * Request error\n */\nexport interface RequestError {\n /** Error code */\n code: string;\n\n /** Human-readable error message */\n message: string;\n\n /** Number of events affected by this error */\n eventCount?: number;\n}\n","export * as mapping from './mapping';\nexport * as basic from './basic';\n","import type { DestinationDataManager } from '..';\nimport { isObject } from '@walkeros/core';\n\n/**\n * Purchase event mapping for Google Ads conversion\n */\nexport const Purchase: DestinationDataManager.Rule = {\n name: 'purchase',\n data: {\n map: {\n // Required fields\n transactionId: 'data.id',\n conversionValue: 'data.total',\n currency: { key: 'data.currency', value: 'USD' },\n eventName: { value: 'purchase' },\n\n // User identification\n userId: 'user.id',\n email: 'user.id', // Will be hashed automatically\n\n // Attribution identifiers (captured by browser source from URL)\n gclid: 'context.gclid', // Google Click ID\n gbraid: 'context.gbraid', // iOS attribution\n wbraid: 'context.wbraid', // Web-to-app\n\n // Shopping cart data\n cartData: {\n map: {\n items: {\n loop: [\n 'nested',\n {\n condition: (entity) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n merchantProductId: 'data.id',\n price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n },\n};\n\n/**\n * Lead event mapping\n */\nexport const Lead: DestinationDataManager.Rule = {\n name: 'generate_lead',\n data: {\n map: {\n eventName: { value: 'generate_lead' },\n conversionValue: { value: 10 },\n currency: { value: 'USD' },\n },\n },\n};\n\n/**\n * Page view mapping for GA4\n */\nexport const PageView: DestinationDataManager.Rule = {\n name: 'page_view',\n data: {\n map: {\n eventName: { value: 'page_view' },\n },\n },\n};\n\n/**\n * Complete mapping configuration\n */\nexport const mapping = {\n order: {\n complete: Purchase,\n },\n lead: {\n submit: Lead,\n },\n page: {\n view: PageView,\n },\n} satisfies DestinationDataManager.Rules;\n\n/**\n * User data mapping configuration\n * Maps walkerOS user properties to Data Manager user identifiers\n */\nexport const userDataMapping: DestinationDataManager.Config = {\n settings: {\n accessToken: 'ya29.c.xxx',\n destinations: [\n {\n operatingAccount: {\n accountId: '123-456-7890',\n accountType: 'GOOGLE_ADS',\n },\n productDestinationId: 'AW-CONVERSION-123',\n },\n ],\n },\n data: {\n map: {\n email: 'user.id',\n phone: 'data.phone',\n firstName: 'data.firstName',\n lastName: 'data.lastName',\n regionCode: 'data.country',\n postalCode: 'data.zip',\n },\n },\n mapping,\n};\n","import type { DestinationDataManager } from '..';\n\n/**\n * Minimal configuration for Google Data Manager\n */\nexport const minimal: DestinationDataManager.Config = {\n settings: {\n accessToken: 'ya29.c.xxx',\n destinations: [\n {\n operatingAccount: {\n accountId: '123-456-7890',\n accountType: 'GOOGLE_ADS',\n },\n productDestinationId: 'AW-CONVERSION-123',\n },\n ],\n },\n};\n\n/**\n * Complete configuration with all options\n */\nexport const complete: DestinationDataManager.Config = {\n settings: {\n accessToken: 'ya29.c.xxx',\n destinations: [\n {\n operatingAccount: {\n accountId: '123-456-7890',\n accountType: 'GOOGLE_ADS',\n },\n productDestinationId: 'AW-CONVERSION-123',\n },\n {\n operatingAccount: {\n accountId: '987654321',\n accountType: 'GOOGLE_ANALYTICS_PROPERTY',\n },\n productDestinationId: 'G-XXXXXXXXXX',\n },\n ],\n eventSource: 'WEB',\n batchSize: 100,\n batchInterval: 5000,\n validateOnly: false,\n consent: {\n adUserData: 'CONSENT_GRANTED',\n adPersonalization: 'CONSENT_GRANTED',\n },\n\n // Guided helpers (apply to all events)\n userData: {\n email: 'user.id',\n phone: 'data.phone',\n firstName: 'data.firstName',\n lastName: 'data.lastName',\n },\n userId: 'user.id',\n clientId: 'user.device',\n sessionAttributes: 'context.sessionAttributes',\n },\n data: {\n map: {\n eventSource: { value: 'WEB' },\n },\n },\n};\n\n/**\n * GA4-specific configuration\n */\nexport const ga4: DestinationDataManager.Config = {\n settings: {\n accessToken: 'ya29.c.xxx',\n destinations: [\n {\n operatingAccount: {\n accountId: '123456789',\n accountType: 'GOOGLE_ANALYTICS_PROPERTY',\n },\n productDestinationId: 'G-XXXXXXXXXX',\n },\n ],\n eventSource: 'WEB',\n },\n};\n\n/**\n * Debug configuration with logging enabled\n */\nexport const debug: DestinationDataManager.Config = {\n settings: {\n accessToken: 'ya29.c.xxx',\n destinations: [\n {\n operatingAccount: {\n accountId: '123-456-7890',\n accountType: 'GOOGLE_ADS',\n },\n productDestinationId: 'AW-CONVERSION-123',\n },\n ],\n logLevel: 'debug', // Shows all API calls and responses\n },\n};\n","// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nimport { schemas } from './schemas/index';\n\nexport { schemas };\n","import { z } from '@walkeros/core';\n\nexport const AccountTypeSchema = z.enum([\n 'GOOGLE_ADS',\n 'DISPLAY_VIDEO_ADVERTISER',\n 'DISPLAY_VIDEO_PARTNER',\n 'GOOGLE_ANALYTICS_PROPERTY',\n]);\n\nexport const EventSourceSchema = z.enum([\n 'WEB',\n 'APP',\n 'IN_STORE',\n 'PHONE',\n 'OTHER',\n]);\n\nexport const ConsentStatusSchema = z.enum([\n 'CONSENT_GRANTED',\n 'CONSENT_DENIED',\n]);\n\nexport const ConsentSchema = z.object({\n adUserData: ConsentStatusSchema.describe(\n 'Consent for data collection and use',\n ).optional(),\n adPersonalization: ConsentStatusSchema.describe(\n 'Consent for ad personalization',\n ).optional(),\n});\n\nexport const OperatingAccountSchema = z.object({\n accountId: z\n .string()\n .min(1)\n .describe('Account ID (e.g., \"123-456-7890\" for Google Ads)'),\n accountType: AccountTypeSchema.describe('Type of account'),\n});\n\nexport const DestinationSchema = z.object({\n operatingAccount: OperatingAccountSchema.describe(\n 'Operating account details',\n ),\n productDestinationId: z\n .string()\n .min(1)\n .describe(\n 'Product-specific destination ID (conversion action or user list)',\n ),\n});\n","import { z } from '@walkeros/core';\nimport {\n DestinationSchema,\n EventSourceSchema,\n ConsentSchema,\n} from './primitives';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'OAuth 2.0 access token with datamanager scope (like ya29.c.xxx)',\n ),\n destinations: z\n .array(DestinationSchema)\n .min(1)\n .max(10)\n .describe(\n 'Array of destination accounts and conversion actions/user lists (max 10)',\n ),\n eventSource: EventSourceSchema.describe(\n 'Default event source if not specified per event (like WEB)',\n ).optional(),\n batchSize: z\n .number()\n .int()\n .min(1)\n .max(2000)\n .describe(\n 'Maximum number of events to batch before sending (max 2000, like 100)',\n )\n .optional(),\n batchInterval: z\n .number()\n .int()\n .min(0)\n .describe(\n 'Time in milliseconds to wait before auto-flushing batch (like 5000)',\n )\n .optional(),\n validateOnly: z\n .boolean()\n .describe('If true, validate request without ingestion (testing mode)')\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Override API endpoint for testing (like https://datamanager.googleapis.com/v1)',\n )\n .optional(),\n consent: ConsentSchema.describe(\n 'Request-level consent for all events',\n ).optional(),\n testEventCode: z\n .string()\n .describe('Test event code for debugging (like TEST12345)')\n .optional(),\n logLevel: z\n .enum(['debug', 'info', 'warn', 'error', 'none'])\n .describe('Log level for debugging (debug shows all API calls)')\n .optional(),\n userData: z\n .record(z.string(), z.unknown())\n .describe(\n \"Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })\",\n )\n .optional(),\n userId: z\n .any()\n .describe(\n \"Guided helper: First-party user ID for all events (like 'user.id')\",\n )\n .optional(),\n clientId: z\n .any()\n .describe(\n \"Guided helper: GA4 client ID for all events (like 'user.device')\",\n )\n .optional(),\n sessionAttributes: z\n .any()\n .describe(\n \"Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')\",\n )\n .optional(),\n consentAdUserData: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'marketing') or static boolean value\",\n )\n .optional(),\n consentAdPersonalization: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'targeting') or static boolean value\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core';\n\n// Data Manager uses flexible mapping via walkerOS mapping system\n// No event-specific mapping schema needed (similar to Meta CAPI pattern)\nexport const MappingSchema = z.object({});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * from './primitives';\nexport * from './settings';\nexport * from './mapping';\n\nimport { zodToSchema } from '@walkeros/core';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nimport type { JSONSchema } from '@walkeros/core';\n\nexport const schemas: Record<string, JSONSchema> = {\n settings: zodToSchema(SettingsSchema),\n mapping: zodToSchema(MappingSchema),\n};\n","import type { DestinationInterface } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationDataManager from './types';\n\n// Examples\nexport * as examples from './examples';\n\n// Schemas\nexport * as schemas from './schemas';\n\nexport const destinationDataManager: DestinationInterface = {\n type: 'datamanager',\n\n config: {},\n\n async init({ config: partialConfig }) {\n const config = getConfig(partialConfig);\n return config;\n },\n\n async push(event, { config, mapping, data, collector, env }) {\n return await push(event, { config, mapping, data, collector, env });\n },\n};\n\nexport default destinationDataManager;\n"],"mappings":";;;;;;;AACA,SAAS,kBAAkB;AAEpB,SAAS,UAAU,gBAA+B,CAAC,GAAW;AACnE,QAAM,WAAY,cAAc,YAAY,CAAC;AAC7C,QAAM,EAAE,aAAa,aAAa,IAAI;AAEtC,MAAI,CAAC,YAAa,YAAW,qCAAqC;AAClE,MAAI,CAAC,gBAAgB,aAAa,WAAW;AAC3C,eAAW,+CAA+C;AAE5D,QAAM,iBAA2B;AAAA,IAC/B,GAAG;AAAA,IACH;AAAA,IACA;AAAA,EACF;AAEA,SAAO,EAAE,GAAG,eAAe,UAAU,eAAe;AACtD;;;AChBA,SAAS,iBAAiB,gBAAgB;;;ACD1C,SAAS,YAAAA,WAAU,iBAAiB;;;ACDpC,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAW9B,eAAsB,UAAU,OAAgC;AAC9D,MAAI,CAAC,SAAS,KAAK,KAAK,CAAC,MAAO,QAAO;AAGvC,MAAI,aAAa,MAAM,KAAK,EAAE,YAAY;AAG1C,MACE,WAAW,SAAS,YAAY,KAChC,WAAW,SAAS,iBAAiB,GACrC;AACA,UAAM,CAAC,WAAW,MAAM,IAAI,WAAW,MAAM,GAAG;AAChD,iBAAa,GAAG,UAAU,QAAQ,OAAO,EAAE,CAAC,IAAI,MAAM;AAAA,EACxD;AAEA,SAAO,cAAc,UAAU;AACjC;AAaA,eAAsB,UAAU,OAAgC;AAC9D,MAAI,CAAC,SAAS,KAAK,KAAK,CAAC,MAAO,QAAO;AAGvC,MAAI,aAAa,MAAM,KAAK;AAG5B,QAAM,UAAU,WAAW,WAAW,GAAG;AAGzC,eAAa,WAAW,QAAQ,OAAO,EAAE;AAGzC,MAAI,WAAW,WAAW,SAAS,IAAI;AACrC,iBAAa,IAAI,UAAU;AAAA,EAC7B,OAAO;AAEL,iBAAa,KAAK,UAAU;AAAA,EAC9B;AAEA,SAAO,cAAc,UAAU;AACjC;AAYA,eAAsB,SACpB,MACA,OAA2B,SACV;AACjB,MAAI,CAAC,SAAS,IAAI,KAAK,CAAC,KAAM,QAAO;AAGrC,MAAI,aAAa,KAAK,KAAK,EAAE,YAAY;AAGzC,MAAI,SAAS,SAAS;AACpB,UAAM,WAAW,CAAC,OAAO,QAAQ,OAAO,SAAS,OAAO,OAAO;AAC/D,eAAW,UAAU,UAAU;AAC7B,UAAI,WAAW,WAAW,MAAM,GAAG;AACjC,qBAAa,WAAW,UAAU,OAAO,MAAM,EAAE,KAAK;AACtD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAIA,MAAI,SAAS,UAAU;AACrB,UAAM,WAAW,CAAC,OAAO,OAAO,OAAO,MAAM,MAAM,GAAG;AACtD,eAAW,UAAU,UAAU;AAE7B,YAAM,kBAAkB,IAAI,MAAM;AAClC,UAAI,WAAW,SAAS,eAAe,GAAG;AACxC,qBAAa,WACV,UAAU,GAAG,WAAW,SAAS,gBAAgB,MAAM,EACvD,KAAK;AACR;AAAA,MACF;AAEA,UAAI,WAAW,SAAS,MAAM,GAAG;AAC/B,qBAAa,WACV,UAAU,GAAG,WAAW,SAAS,OAAO,MAAM,EAC9C,KAAK;AACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,cAAc,UAAU;AACjC;;;ADpGO,SAAS,gBAAgB,WAA2B;AACzD,SAAO,IAAI,KAAK,SAAS,EAAE,YAAY;AACzC;AASA,eAAsB,eACpB,MAC+B;AAC/B,QAAM,cAAgC,CAAC;AAIvC,MAAIC,UAAS,KAAK,KAAK,KAAK,KAAK,OAAO;AACtC,UAAM,cAAc,MAAM,UAAU,KAAK,KAAK;AAC9C,QAAI,aAAa;AACf,kBAAY,KAAK,EAAE,cAAc,YAAY,CAAC;AAAA,IAChD;AAAA,EACF;AAGA,MAAIA,UAAS,KAAK,KAAK,KAAK,KAAK,OAAO;AACtC,UAAM,cAAc,MAAM,UAAU,KAAK,KAAK;AAC9C,QAAI,aAAa;AACf,kBAAY,KAAK,EAAE,aAAa,YAAY,CAAC;AAAA,IAC/C;AAAA,EACF;AAGA,QAAM,aACJ,KAAK,aAAa,KAAK,YAAY,KAAK,cAAc,KAAK;AAE7D,MAAI,YAAY;AACd,UAAM,UAAkC,CAAC;AAEzC,QAAIA,UAAS,KAAK,SAAS,KAAK,KAAK,WAAW;AAC9C,cAAQ,YAAY,MAAM,SAAS,KAAK,WAAW,OAAO;AAAA,IAC5D;AAEA,QAAIA,UAAS,KAAK,QAAQ,KAAK,KAAK,UAAU;AAC5C,cAAQ,aAAa,MAAM,SAAS,KAAK,UAAU,QAAQ;AAAA,IAC7D;AAGA,QAAIA,UAAS,KAAK,UAAU,KAAK,KAAK,YAAY;AAChD,cAAQ,aAAa,KAAK,WAAW,YAAY;AAAA,IACnD;AAGA,QAAIA,UAAS,KAAK,UAAU,KAAK,KAAK,YAAY;AAChD,cAAQ,aAAa,KAAK;AAAA,IAC5B;AAEA,QAAI,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AACnC,kBAAY,KAAK,EAAE,QAAQ,CAAC;AAAA,IAC9B;AAAA,EACF;AAGA,MAAI,YAAY,WAAW,EAAG,QAAO;AAErC,SAAO;AAAA,IACL,iBAAiB,YAAY,MAAM,GAAG,EAAE;AAAA,EAC1C;AACF;AASO,SAAS,oBACd,MAC2B;AAC3B,QAAM,cAA6B,CAAC;AAGpC,MAAIA,UAAS,KAAK,KAAK,KAAK,KAAK,OAAO;AACtC,gBAAY,QAAQ,KAAK;AAAA,EAC3B;AACA,MAAIA,UAAS,KAAK,MAAM,KAAK,KAAK,QAAQ;AACxC,gBAAY,SAAS,KAAK;AAAA,EAC5B;AACA,MAAIA,UAAS,KAAK,MAAM,KAAK,KAAK,QAAQ;AACxC,gBAAY,SAAS,KAAK;AAAA,EAC5B;AACA,MAAIA,UAAS,KAAK,iBAAiB,KAAK,KAAK,mBAAmB;AAC9D,gBAAY,oBAAoB,KAAK;AAAA,EACvC;AAEA,SAAO,OAAO,KAAK,WAAW,EAAE,SAAS,IAAI,cAAc;AAC7D;AASO,SAAS,cACd,iBACqB;AACrB,MAAI,CAAC,gBAAiB,QAAO;AAE7B,QAAM,UAAmB,CAAC;AAG1B,MAAI,UAAU,gBAAgB,SAAS,GAAG;AACxC,YAAQ,aAAa,gBAAgB,YACjC,oBACA;AAAA,EACN;AAGA,MAAI,UAAU,gBAAgB,eAAe,GAAG;AAC9C,YAAQ,oBAAoB,gBAAgB,kBACxC,oBACA;AAAA,EACN;AAEA,SAAO,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AACrD;AAMA,eAAsB,YACpB,OACA,YACgB;AAChB,QAAM,mBAA0B;AAAA,IAC9B,gBAAgB,gBAAgB,MAAM,SAAS;AAAA,EACjD;AAGA,QAAM,OAAO,cAAc,CAAC;AAG5B,MAAIA,UAAS,KAAK,aAAa,KAAK,KAAK,eAAe;AACtD,qBAAiB,gBAAgB,KAAK,cAAc,UAAU,GAAG,GAAG;AAAA,EACtE;AAGA,MAAIA,UAAS,KAAK,QAAQ,KAAK,KAAK,UAAU;AAC5C,qBAAiB,WAAW,KAAK,SAAS,UAAU,GAAG,GAAG;AAAA,EAC5D;AAGA,MAAIA,UAAS,KAAK,MAAM,KAAK,KAAK,QAAQ;AACxC,qBAAiB,SAAS,KAAK,OAAO,UAAU,GAAG,GAAG;AAAA,EACxD;AAGA,QAAM,WAAW,MAAM,eAAe,IAAI;AAC1C,MAAI,UAAU;AACZ,qBAAiB,WAAW;AAAA,EAC9B;AAGA,QAAM,gBAAgB,oBAAoB,IAAI;AAC9C,MAAI,eAAe;AACjB,qBAAiB,gBAAgB;AAAA,EACnC;AAGA,MAAI,OAAO,KAAK,oBAAoB,UAAU;AAC5C,qBAAiB,kBAAkB,KAAK;AAAA,EAC1C;AAGA,MAAIA,UAAS,KAAK,QAAQ,KAAK,KAAK,UAAU;AAC5C,qBAAiB,WAAW,KAAK,SAAS,UAAU,GAAG,CAAC,EAAE,YAAY;AAAA,EACxE;AAGA,MAAI,KAAK,YAAY,OAAO,KAAK,aAAa,UAAU;AACtD,qBAAiB,WAAW,KAAK;AAAA,EACnC;AAGA,MAAIA,UAAS,KAAK,SAAS,KAAK,KAAK,WAAW;AAC9C,qBAAiB,YAAY,KAAK,UAAU,UAAU,GAAG,EAAE;AAAA,EAC7D;AAGA,MAAIA,UAAS,KAAK,WAAW,KAAK,KAAK,aAAa;AAClD,qBAAiB,cAAc,KAAK;AAAA,EACtC;AAGA,QAAM,gBAAyB,CAAC;AAGhC,MAAI,OAAO,KAAK,eAAe,WAAW;AACxC,kBAAc,aAAa,KAAK,aAC5B,oBACA;AAAA,EACN;AACA,MAAI,OAAO,KAAK,sBAAsB,WAAW;AAC/C,kBAAc,oBAAoB,KAAK,oBACnC,oBACA;AAAA,EACN;AAGA,MAAI,OAAO,KAAK,aAAa,EAAE,WAAW,GAAG;AAC3C,UAAM,eAAe,cAAc,MAAM,OAAO;AAChD,QAAI,cAAc;AAChB,uBAAiB,UAAU;AAAA,IAC7B;AAAA,EACF,OAAO;AACL,qBAAiB,UAAU;AAAA,EAC7B;AAEA,SAAO;AACT;;;AE/OO,SAAS,aAAa,QAAkB,QAAQ;AACrD,QAAM,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE;AAC/D,QAAM,eAAe,OAAO,KAAK;AAEjC,SAAO;AAAA,IACL,OAAO,CAAC,SAAiB,SAAmB;AAC1C,UAAI,gBAAgB;AAClB,gBAAQ,IAAI,iBAAiB,OAAO,IAAI,QAAQ,EAAE;AAAA,IACtD;AAAA,IACA,MAAM,CAAC,SAAiB,SAAmB;AACzC,UAAI,gBAAgB;AAClB,gBAAQ,IAAI,iBAAiB,OAAO,IAAI,QAAQ,EAAE;AAAA,IACtD;AAAA,IACA,MAAM,CAAC,SAAiB,SAAmB;AACzC,UAAI,gBAAgB;AAClB,gBAAQ,KAAK,iBAAiB,OAAO,IAAI,QAAQ,EAAE;AAAA,IACvD;AAAA,IACA,OAAO,CAAC,SAAiB,SAAmB;AAC1C,UAAI,gBAAgB;AAClB,gBAAQ,MAAM,iBAAiB,OAAO,IAAI,QAAQ,EAAE;AAAA,IACxD;AAAA,EACF;AACF;;;AHnBO,IAAM,OAAe,eAC1B,OACA,EAAE,QAAQ,SAAAC,UAAS,MAAM,WAAW,IAAI,GACxC;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,OAAO;AAEX,QAAM,SAAS,aAAa,QAAQ;AAGpC,QAAM,iBAAiB,WACnB,MAAM,gBAAgB,OAAO,EAAE,KAAK,SAAS,CAAC,IAC9C,CAAC;AACL,QAAM,eAAe,SACjB,MAAM,gBAAgB,OAAO,MAAM,IACnC;AACJ,QAAM,iBAAiB,WACnB,MAAM,gBAAgB,OAAO,QAAQ,IACrC;AACJ,QAAM,0BAA0B,oBAC5B,MAAM,gBAAgB,OAAO,iBAAiB,IAC9C;AAGJ,QAAM,yBACJ,OAAO,sBAAsB,YACzB,oBACA,OAAO,sBAAsB,YAAY,MAAM,UAC7C,MAAM,QAAQ,iBAAiB,IAC/B;AAER,QAAM,gCACJ,OAAO,6BAA6B,YAChC,2BACA,OAAO,6BAA6B,YAAY,MAAM,UACpD,MAAM,QAAQ,wBAAwB,IACtC;AAGR,QAAM,kBAA2C,CAAC;AAClD,MAAI,SAAS,cAAc,GAAG;AAC5B,WAAO,OAAO,iBAAiB,cAAc;AAAA,EAC/C;AACA,MAAI,iBAAiB,OAAW,iBAAgB,SAAS;AACzD,MAAI,mBAAmB,OAAW,iBAAgB,WAAW;AAC7D,MAAI,4BAA4B;AAC9B,oBAAgB,oBAAoB;AACtC,MAAI,2BAA2B;AAC7B,oBAAgB,aAAa;AAC/B,MAAI,kCAAkC;AACpC,oBAAgB,oBAAoB;AAGtC,QAAM,aAAa,OAAO,OACtB,MAAM,gBAAgB,OAAO,OAAO,IAAI,IACxC,CAAC;AACL,QAAM,YAAY,SAAS,IAAI,IAAI,OAAO,CAAC;AAG3C,QAAM,YAAY;AAAA,IAChB,GAAG;AAAA,IACH,GAAI,SAAS,UAAU,IAAI,aAAa,CAAC;AAAA,IACzC,GAAG;AAAA,EACL;AAGA,QAAM,mBAAmB,MAAM,YAAY,OAAO,SAAS;AAE3D,SAAO,MAAM,oBAAoB;AAAA,IAC/B,MAAM,MAAM;AAAA,IACZ,IAAI,MAAM;AAAA,IACV,WAAW,MAAM;AAAA,EACnB,CAAC;AAGD,MAAI,CAAC,iBAAiB,eAAe,aAAa;AAChD,qBAAiB,cAAc;AAAA,EACjC;AAGA,MAAI,CAAC,iBAAiB,WAAW,gBAAgB;AAC/C,qBAAiB,UAAU;AAAA,EAC7B;AAGA,QAAM,cAAmC;AAAA,IACvC,QAAQ,CAAC,gBAAgB;AAAA,IACzB;AAAA,EACF;AAGA,MAAI,gBAAgB;AAClB,gBAAY,UAAU;AAAA,EACxB;AAEA,MAAI,cAAc;AAChB,gBAAY,eAAe;AAAA,EAC7B;AAEA,MAAI,eAAe;AACjB,gBAAY,gBAAgB;AAAA,EAC9B;AAGA,QAAM,WAAU,2BAAK,UAAS;AAC9B,QAAM,WAAW,GAAG,GAAG;AAEvB,SAAO,MAAM,+BAA+B;AAAA,IAC1C;AAAA,IACA,YAAY,YAAY,OAAO;AAAA,IAC/B,cAAc,aAAa;AAAA,IAC3B;AAAA,EACF,CAAC;AAED,QAAM,WAAW,MAAM,QAAQ,UAAU;AAAA,IACvC,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,eAAe,UAAU,WAAW;AAAA,MACpC,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,UAAU,WAAW;AAAA,EAClC,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,YAAY,MAAM,SAAS,KAAK;AACtC,WAAO,MAAM,sBAAsB;AAAA,MACjC,QAAQ,SAAS;AAAA,MACjB,OAAO;AAAA,IACT,CAAC;AACD,UAAM,IAAI;AAAA,MACR,2BAA2B,SAAS,MAAM,MAAM,SAAS;AAAA,IAC3D;AAAA,EACF;AAEA,QAAM,SAA+B,MAAM,SAAS,KAAK;AAEzD,SAAO,MAAM,gBAAgB;AAAA,IAC3B,QAAQ,SAAS;AAAA,IACjB,WAAW,OAAO;AAAA,EACpB,CAAC;AAGD,MAAI,OAAO,oBAAoB,OAAO,iBAAiB,SAAS,GAAG;AACjE,WAAO,MAAM,qBAAqB;AAAA,MAChC,QAAQ,OAAO;AAAA,IACjB,CAAC;AACD,UAAM,IAAI;AAAA,MACR,sBAAsB,KAAK,UAAU,OAAO,gBAAgB,CAAC;AAAA,IAC/D;AAAA,EACF;AAEA,SAAO,KAAK,gCAAgC;AAAA,IAC1C,WAAW,OAAO;AAAA,EACpB,CAAC;AACH;;;AI9KA;;;ACAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,SAAS,YAAAC,iBAAgB;AAKlB,IAAM,WAAwC;AAAA,EACnD,MAAM;AAAA,EACN,MAAM;AAAA,IACJ,KAAK;AAAA;AAAA,MAEH,eAAe;AAAA,MACf,iBAAiB;AAAA,MACjB,UAAU,EAAE,KAAK,iBAAiB,OAAO,MAAM;AAAA,MAC/C,WAAW,EAAE,OAAO,WAAW;AAAA;AAAA,MAG/B,QAAQ;AAAA,MACR,OAAO;AAAA;AAAA;AAAA,MAGP,OAAO;AAAA;AAAA,MACP,QAAQ;AAAA;AAAA,MACR,QAAQ;AAAA;AAAA;AAAA,MAGR,UAAU;AAAA,QACR,KAAK;AAAA,UACH,OAAO;AAAA,YACL,MAAM;AAAA,cACJ;AAAA,cACA;AAAA,gBACE,WAAW,CAAC,WACVA,UAAS,MAAM,KAAK,OAAO,WAAW;AAAA,gBACxC,KAAK;AAAA,kBACH,mBAAmB;AAAA,kBACnB,OAAO;AAAA,kBACP,UAAU,EAAE,KAAK,iBAAiB,OAAO,EAAE;AAAA,gBAC7C;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAKO,IAAM,OAAoC;AAAA,EAC/C,MAAM;AAAA,EACN,MAAM;AAAA,IACJ,KAAK;AAAA,MACH,WAAW,EAAE,OAAO,gBAAgB;AAAA,MACpC,iBAAiB,EAAE,OAAO,GAAG;AAAA,MAC7B,UAAU,EAAE,OAAO,MAAM;AAAA,IAC3B;AAAA,EACF;AACF;AAKO,IAAM,WAAwC;AAAA,EACnD,MAAM;AAAA,EACN,MAAM;AAAA,IACJ,KAAK;AAAA,MACH,WAAW,EAAE,OAAO,YAAY;AAAA,IAClC;AAAA,EACF;AACF;AAKO,IAAM,UAAU;AAAA,EACrB,OAAO;AAAA,IACL,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,QAAQ;AAAA,EACV;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,EACR;AACF;AAMO,IAAM,kBAAiD;AAAA,EAC5D,UAAU;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,MACZ;AAAA,QACE,kBAAkB;AAAA,UAChB,WAAW;AAAA,UACX,aAAa;AAAA,QACf;AAAA,QACA,sBAAsB;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM;AAAA,IACJ,KAAK;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,MACP,WAAW;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,YAAY;AAAA,IACd;AAAA,EACF;AAAA,EACA;AACF;;;ACrHA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKO,IAAM,UAAyC;AAAA,EACpD,UAAU;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,MACZ;AAAA,QACE,kBAAkB;AAAA,UAChB,WAAW;AAAA,UACX,aAAa;AAAA,QACf;AAAA,QACA,sBAAsB;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AACF;AAKO,IAAM,WAA0C;AAAA,EACrD,UAAU;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,MACZ;AAAA,QACE,kBAAkB;AAAA,UAChB,WAAW;AAAA,UACX,aAAa;AAAA,QACf;AAAA,QACA,sBAAsB;AAAA,MACxB;AAAA,MACA;AAAA,QACE,kBAAkB;AAAA,UAChB,WAAW;AAAA,UACX,aAAa;AAAA,QACf;AAAA,QACA,sBAAsB;AAAA,MACxB;AAAA,IACF;AAAA,IACA,aAAa;AAAA,IACb,WAAW;AAAA,IACX,eAAe;AAAA,IACf,cAAc;AAAA,IACd,SAAS;AAAA,MACP,YAAY;AAAA,MACZ,mBAAmB;AAAA,IACrB;AAAA;AAAA,IAGA,UAAU;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,MACP,WAAW;AAAA,MACX,UAAU;AAAA,IACZ;AAAA,IACA,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA,MAAM;AAAA,IACJ,KAAK;AAAA,MACH,aAAa,EAAE,OAAO,MAAM;AAAA,IAC9B;AAAA,EACF;AACF;AAKO,IAAM,MAAqC;AAAA,EAChD,UAAU;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,MACZ;AAAA,QACE,kBAAkB;AAAA,UAChB,WAAW;AAAA,UACX,aAAa;AAAA,QACf;AAAA,QACA,sBAAsB;AAAA,MACxB;AAAA,IACF;AAAA,IACA,aAAa;AAAA,EACf;AACF;AAKO,IAAM,QAAuC;AAAA,EAClD,UAAU;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,MACZ;AAAA,QACE,kBAAkB;AAAA,UAChB,WAAW;AAAA,UACX,aAAa;AAAA,QACf;AAAA,QACA,sBAAsB;AAAA,MACxB;AAAA,IACF;AAAA,IACA,UAAU;AAAA;AAAA,EACZ;AACF;;;ACzGA;AAAA;AAAA;AAAA;;;ACAA,SAAS,SAAS;AAEX,IAAM,oBAAoB,EAAE,KAAK;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,oBAAoB,EAAE,KAAK;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,sBAAsB,EAAE,KAAK;AAAA,EACxC;AAAA,EACA;AACF,CAAC;AAEM,IAAM,gBAAgB,EAAE,OAAO;AAAA,EACpC,YAAY,oBAAoB;AAAA,IAC9B;AAAA,EACF,EAAE,SAAS;AAAA,EACX,mBAAmB,oBAAoB;AAAA,IACrC;AAAA,EACF,EAAE,SAAS;AACb,CAAC;AAEM,IAAM,yBAAyB,EAAE,OAAO;AAAA,EAC7C,WAAW,EACR,OAAO,EACP,IAAI,CAAC,EACL,SAAS,kDAAkD;AAAA,EAC9D,aAAa,kBAAkB,SAAS,iBAAiB;AAC3D,CAAC;AAEM,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,kBAAkB,uBAAuB;AAAA,IACvC;AAAA,EACF;AAAA,EACA,sBAAsB,EACnB,OAAO,EACP,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF;AACJ,CAAC;;;ACjDD,SAAS,KAAAC,UAAS;AAOX,IAAM,iBAAiBC,GAAE,OAAO;AAAA,EACrC,aAAaA,GACV,OAAO,EACP,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF;AAAA,EACF,cAAcA,GACX,MAAM,iBAAiB,EACvB,IAAI,CAAC,EACL,IAAI,EAAE,EACN;AAAA,IACC;AAAA,EACF;AAAA,EACF,aAAa,kBAAkB;AAAA,IAC7B;AAAA,EACF,EAAE,SAAS;AAAA,EACX,WAAWA,GACR,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,GAAI,EACR;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,eAAeA,GACZ,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,cAAcA,GACX,QAAQ,EACR,SAAS,4DAA4D,EACrE,SAAS;AAAA,EACZ,KAAKA,GACF,OAAO,EACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,SAAS,cAAc;AAAA,IACrB;AAAA,EACF,EAAE,SAAS;AAAA,EACX,eAAeA,GACZ,OAAO,EACP,SAAS,gDAAgD,EACzD,SAAS;AAAA,EACZ,UAAUA,GACP,KAAK,CAAC,SAAS,QAAQ,QAAQ,SAAS,MAAM,CAAC,EAC/C,SAAS,qDAAqD,EAC9D,SAAS;AAAA,EACZ,UAAUA,GACP,OAAOA,GAAE,OAAO,GAAGA,GAAE,QAAQ,CAAC,EAC9B;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,QAAQA,GACL,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,UAAUA,GACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,mBAAmBA,GAChB,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,mBAAmBA,GAChB,MAAM,CAACA,GAAE,OAAO,GAAGA,GAAE,QAAQ,CAAC,CAAC,EAC/B;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,0BAA0BA,GACvB,MAAM,CAACA,GAAE,OAAO,GAAGA,GAAE,QAAQ,CAAC,CAAC,EAC/B;AAAA,IACC;AAAA,EACF,EACC,SAAS;AACd,CAAC;;;ACnGD,SAAS,KAAAC,UAAS;AAIX,IAAM,gBAAgBA,GAAE,OAAO,CAAC,CAAC;;;ACAxC,SAAS,mBAAmB;AAMrB,IAAM,UAAsC;AAAA,EACjD,UAAU,YAAY,cAAc;AAAA,EACpC,SAAS,YAAY,aAAa;AACpC;;;ACAO,IAAM,yBAA+C;AAAA,EAC1D,MAAM;AAAA,EAEN,QAAQ,CAAC;AAAA,EAET,MAAM,KAAK,EAAE,QAAQ,cAAc,GAAG;AACpC,UAAM,SAAS,UAAU,aAAa;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,OAAO,EAAE,QAAQ,SAAAC,UAAS,MAAM,WAAW,IAAI,GAAG;AAC3D,WAAO,MAAM,KAAK,OAAO,EAAE,QAAQ,SAAAA,UAAS,MAAM,WAAW,IAAI,CAAC;AAAA,EACpE;AACF;AAEA,IAAO,gBAAQ;","names":["isString","isString","mapping","isObject","z","z","z","mapping"]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/push.ts","../src/format.ts","../src/hash.ts","../src/utils.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, Settings, PartialConfig } from './types';\nimport { throwError } from '@walkeros/core';\n\nexport function getConfig(partialConfig: PartialConfig = {}): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { accessToken, destinations } = settings;\n\n if (!accessToken) throwError('Config settings accessToken missing');\n if (!destinations || destinations.length === 0)\n throwError('Config settings destinations missing or empty');\n\n const settingsConfig: Settings = {\n ...settings,\n accessToken,\n destinations,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { PushFn } from './types';\nimport type { IngestEventsRequest, IngestEventsResponse } from './types';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { formatEvent, formatConsent } from './format';\nimport { createLogger } from './utils';\n\nexport const push: PushFn = async function (\n event,\n { config, mapping, data, collector, env },\n) {\n const {\n accessToken,\n destinations,\n eventSource,\n validateOnly = false,\n url = 'https://datamanager.googleapis.com/v1',\n consent: requestConsent,\n testEventCode,\n logLevel = 'none',\n userData,\n userId,\n clientId,\n sessionAttributes,\n consentAdUserData,\n consentAdPersonalization,\n } = config.settings!;\n\n const logger = createLogger(logLevel);\n\n // Extract Settings guided helpers\n const userDataMapped = userData\n ? await getMappingValue(event, { map: userData })\n : {};\n const userIdMapped = userId\n ? await getMappingValue(event, userId)\n : undefined;\n const clientIdMapped = clientId\n ? await getMappingValue(event, clientId)\n : undefined;\n const sessionAttributesMapped = sessionAttributes\n ? await getMappingValue(event, sessionAttributes)\n : undefined;\n\n // Extract consent from Settings\n const consentAdUserDataValue =\n typeof consentAdUserData === 'boolean'\n ? consentAdUserData\n : typeof consentAdUserData === 'string' && event.consent\n ? event.consent[consentAdUserData]\n : undefined;\n\n const consentAdPersonalizationValue =\n typeof consentAdPersonalization === 'boolean'\n ? consentAdPersonalization\n : typeof consentAdPersonalization === 'string' && event.consent\n ? event.consent[consentAdPersonalization]\n : undefined;\n\n // Build Settings helpers object\n const settingsHelpers: Record<string, unknown> = {};\n if (isObject(userDataMapped)) {\n Object.assign(settingsHelpers, userDataMapped);\n }\n if (userIdMapped !== undefined) settingsHelpers.userId = userIdMapped;\n if (clientIdMapped !== undefined) settingsHelpers.clientId = clientIdMapped;\n if (sessionAttributesMapped !== undefined)\n settingsHelpers.sessionAttributes = sessionAttributesMapped;\n if (consentAdUserDataValue !== undefined)\n settingsHelpers.adUserData = consentAdUserDataValue;\n if (consentAdPersonalizationValue !== undefined)\n settingsHelpers.adPersonalization = consentAdPersonalizationValue;\n\n // Get mapped data from destination config and event mapping\n const configData = config.data\n ? await getMappingValue(event, config.data)\n : {};\n const eventData = isObject(data) ? data : {};\n\n // Merge: Settings helpers < config.data < event mapping data\n const finalData = {\n ...settingsHelpers,\n ...(isObject(configData) ? configData : {}),\n ...eventData,\n };\n\n // Format event for Data Manager API\n const dataManagerEvent = await formatEvent(event, finalData);\n\n logger.debug('Processing event', {\n name: event.name,\n id: event.id,\n timestamp: event.timestamp,\n });\n\n // Apply event source from settings if not set\n if (!dataManagerEvent.eventSource && eventSource) {\n dataManagerEvent.eventSource = eventSource;\n }\n\n // Apply request-level consent if event doesn't have consent\n if (!dataManagerEvent.consent && requestConsent) {\n dataManagerEvent.consent = requestConsent;\n }\n\n // Build API request\n const requestBody: IngestEventsRequest = {\n events: [dataManagerEvent],\n destinations,\n };\n\n // Add optional parameters\n if (requestConsent) {\n requestBody.consent = requestConsent;\n }\n\n if (validateOnly) {\n requestBody.validateOnly = true;\n }\n\n if (testEventCode) {\n requestBody.testEventCode = testEventCode;\n }\n\n // Send to Data Manager API\n const fetchFn = env?.fetch || fetch;\n const endpoint = `${url}/events:ingest`;\n\n logger.debug('Sending to Data Manager API', {\n endpoint,\n eventCount: requestBody.events.length,\n destinations: destinations.length,\n validateOnly,\n });\n\n const response = await fetchFn(endpoint, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n logger.error('API request failed', {\n status: response.status,\n error: errorText,\n });\n throw new Error(\n `Data Manager API error (${response.status}): ${errorText}`,\n );\n }\n\n const result: IngestEventsResponse = await response.json();\n\n logger.debug('API response', {\n status: response.status,\n requestId: result.requestId,\n });\n\n // If validation errors exist, throw them\n if (result.validationErrors && result.validationErrors.length > 0) {\n logger.error('Validation errors', {\n errors: result.validationErrors,\n });\n throw new Error(\n `Validation errors: ${JSON.stringify(result.validationErrors)}`,\n );\n }\n\n logger.info('Event processed successfully', {\n requestId: result.requestId,\n });\n};\n","import type { WalkerOS } from '@walkeros/core';\nimport { isString, isDefined } from '@walkeros/core';\nimport type {\n Event,\n UserData,\n UserIdentifier,\n AdIdentifiers,\n Consent,\n ConsentStatus,\n} from './types';\nimport { hashEmail, hashPhone, hashName } from './hash';\n\n/**\n * Format walkerOS event timestamp to RFC 3339 format\n * https://developers.google.com/data-manager/api/reference/rest/v1/Event\n *\n * walkerOS timestamp is in milliseconds, RFC 3339 format: \"2024-01-15T10:30:00Z\"\n */\nexport function formatTimestamp(timestamp: number): string {\n return new Date(timestamp).toISOString();\n}\n\n/**\n * Format user identifiers from mapped data\n * https://developers.google.com/data-manager/api/reference/rest/v1/UserData\n *\n * User data must be explicitly mapped in the mapping configuration.\n * Max 10 identifiers per event\n */\nexport async function formatUserData(\n data: Record<string, unknown>,\n): Promise<UserData | undefined> {\n const identifiers: UserIdentifier[] = [];\n\n // Extract from mapped data only\n // Email\n if (isString(data.email) && data.email) {\n const hashedEmail = await hashEmail(data.email);\n if (hashedEmail) {\n identifiers.push({ emailAddress: hashedEmail });\n }\n }\n\n // Phone\n if (isString(data.phone) && data.phone) {\n const hashedPhone = await hashPhone(data.phone);\n if (hashedPhone) {\n identifiers.push({ phoneNumber: hashedPhone });\n }\n }\n\n // Address from mapped properties\n const hasAddress =\n data.firstName || data.lastName || data.regionCode || data.postalCode;\n\n if (hasAddress) {\n const address: Record<string, string> = {};\n\n if (isString(data.firstName) && data.firstName) {\n address.givenName = await hashName(data.firstName, 'given');\n }\n\n if (isString(data.lastName) && data.lastName) {\n address.familyName = await hashName(data.lastName, 'family');\n }\n\n // Region code is NOT hashed\n if (isString(data.regionCode) && data.regionCode) {\n address.regionCode = data.regionCode.toUpperCase();\n }\n\n // Postal code is NOT hashed\n if (isString(data.postalCode) && data.postalCode) {\n address.postalCode = data.postalCode;\n }\n\n if (Object.keys(address).length > 0) {\n identifiers.push({ address });\n }\n }\n\n // Limit to 10 identifiers\n if (identifiers.length === 0) return undefined;\n\n return {\n userIdentifiers: identifiers.slice(0, 10),\n };\n}\n\n/**\n * Extract and format attribution identifiers from mapped data\n * https://developers.google.com/data-manager/api/reference/rest/v1/AdIdentifiers\n *\n * Attribution identifiers should be mapped explicitly in the mapping configuration.\n * Example: { gclid: 'context.gclid', gbraid: 'context.gbraid' }\n */\nexport function formatAdIdentifiers(\n data: Record<string, unknown>,\n): AdIdentifiers | undefined {\n const identifiers: AdIdentifiers = {};\n\n // Extract from mapped data (already processed by mapping system)\n if (isString(data.gclid) && data.gclid) {\n identifiers.gclid = data.gclid;\n }\n if (isString(data.gbraid) && data.gbraid) {\n identifiers.gbraid = data.gbraid;\n }\n if (isString(data.wbraid) && data.wbraid) {\n identifiers.wbraid = data.wbraid;\n }\n if (isString(data.sessionAttributes) && data.sessionAttributes) {\n identifiers.sessionAttributes = data.sessionAttributes;\n }\n\n return Object.keys(identifiers).length > 0 ? identifiers : undefined;\n}\n\n/**\n * Map walkerOS consent to Data Manager consent format\n * https://developers.google.com/data-manager/api/devguides/concepts/dma\n *\n * walkerOS: { marketing: true, personalization: false }\n * Data Manager: { adUserData: 'CONSENT_GRANTED', adPersonalization: 'CONSENT_DENIED' }\n */\nexport function formatConsent(\n walkerOSConsent: WalkerOS.Consent | undefined,\n): Consent | undefined {\n if (!walkerOSConsent) return undefined;\n\n const consent: Consent = {};\n\n // Map marketing consent to adUserData\n if (isDefined(walkerOSConsent.marketing)) {\n consent.adUserData = walkerOSConsent.marketing\n ? 'CONSENT_GRANTED'\n : 'CONSENT_DENIED';\n }\n\n // Map personalization consent to adPersonalization\n if (isDefined(walkerOSConsent.personalization)) {\n consent.adPersonalization = walkerOSConsent.personalization\n ? 'CONSENT_GRANTED'\n : 'CONSENT_DENIED';\n }\n\n return Object.keys(consent).length > 0 ? consent : undefined;\n}\n\n/**\n * Format complete event for Data Manager API\n * https://developers.google.com/data-manager/api/reference/rest/v1/Event\n */\nexport async function formatEvent(\n event: WalkerOS.Event,\n mappedData?: Record<string, unknown>,\n): Promise<Event> {\n const dataManagerEvent: Event = {\n eventTimestamp: formatTimestamp(event.timestamp),\n };\n\n // Use only mapped data (no fallback to event.data)\n const data = mappedData || {};\n\n // Transaction ID for deduplication\n if (isString(data.transactionId) && data.transactionId) {\n dataManagerEvent.transactionId = data.transactionId.substring(0, 512);\n }\n\n // Client ID (GA)\n if (isString(data.clientId) && data.clientId) {\n dataManagerEvent.clientId = data.clientId.substring(0, 255);\n }\n\n // User ID\n if (isString(data.userId) && data.userId) {\n dataManagerEvent.userId = data.userId.substring(0, 256);\n }\n\n // User data\n const userData = await formatUserData(data);\n if (userData) {\n dataManagerEvent.userData = userData;\n }\n\n // Attribution identifiers\n const adIdentifiers = formatAdIdentifiers(data);\n if (adIdentifiers) {\n dataManagerEvent.adIdentifiers = adIdentifiers;\n }\n\n // Conversion value\n if (typeof data.conversionValue === 'number') {\n dataManagerEvent.conversionValue = data.conversionValue;\n }\n\n // Currency\n if (isString(data.currency) && data.currency) {\n dataManagerEvent.currency = data.currency.substring(0, 3).toUpperCase();\n }\n\n // Cart data\n if (data.cartData && typeof data.cartData === 'object') {\n dataManagerEvent.cartData = data.cartData as Event['cartData'];\n }\n\n // Event name (for GA4)\n if (isString(data.eventName) && data.eventName) {\n dataManagerEvent.eventName = data.eventName.substring(0, 40);\n }\n\n // Event source\n if (isString(data.eventSource) && data.eventSource) {\n dataManagerEvent.eventSource = data.eventSource as Event['eventSource'];\n }\n\n // Consent - check mapped data first, then fallback to event.consent\n const mappedConsent: Consent = {};\n\n // Check for mapped consent values (from Settings or event mapping)\n if (typeof data.adUserData === 'boolean') {\n mappedConsent.adUserData = data.adUserData\n ? 'CONSENT_GRANTED'\n : 'CONSENT_DENIED';\n }\n if (typeof data.adPersonalization === 'boolean') {\n mappedConsent.adPersonalization = data.adPersonalization\n ? 'CONSENT_GRANTED'\n : 'CONSENT_DENIED';\n }\n\n // If no mapped consent, fall back to event.consent\n if (Object.keys(mappedConsent).length === 0) {\n const eventConsent = formatConsent(event.consent);\n if (eventConsent) {\n dataManagerEvent.consent = eventConsent;\n }\n } else {\n dataManagerEvent.consent = mappedConsent;\n }\n\n return dataManagerEvent;\n}\n","import { isString } from '@walkeros/core';\nimport { getHashServer } from '@walkeros/server-core';\n\n/**\n * Normalize email address according to Google Data Manager requirements\n * https://developers.google.com/data-manager/api/devguides/concepts/formatting#email\n *\n * 1. Trim whitespace\n * 2. Convert to lowercase\n * 3. Remove dots (.) for gmail.com and googlemail.com\n * 4. SHA-256 hash\n */\nexport async function hashEmail(email: string): Promise<string> {\n if (!isString(email) || !email) return '';\n\n // Trim and lowercase\n let normalized = email.trim().toLowerCase();\n\n // Remove dots for Gmail addresses\n if (\n normalized.endsWith('@gmail.com') ||\n normalized.endsWith('@googlemail.com')\n ) {\n const [localPart, domain] = normalized.split('@');\n normalized = `${localPart.replace(/\\./g, '')}@${domain}`;\n }\n\n return getHashServer(normalized);\n}\n\n/**\n * Normalize phone number to E.164 format and hash\n * https://developers.google.com/data-manager/api/devguides/concepts/formatting#phone\n *\n * E.164 format: +[country code][number] (max 15 digits after +)\n * Example: +18005550100\n *\n * 1. Remove all non-digit characters except leading +\n * 2. Ensure it starts with +\n * 3. SHA-256 hash\n */\nexport async function hashPhone(phone: string): Promise<string> {\n if (!isString(phone) || !phone) return '';\n\n // Remove all non-digit characters except + at the start\n let normalized = phone.trim();\n\n // Extract country code if present\n const hasPlus = normalized.startsWith('+');\n\n // Remove all non-digits\n normalized = normalized.replace(/\\D/g, '');\n\n // Add + prefix if it was there or if number is long enough\n if (hasPlus || normalized.length > 10) {\n normalized = `+${normalized}`;\n } else {\n // Assume US number if no country code (default behavior)\n normalized = `+1${normalized}`;\n }\n\n return getHashServer(normalized);\n}\n\n/**\n * Normalize and hash a name (first or last name)\n * https://developers.google.com/data-manager/api/devguides/concepts/formatting#name\n *\n * 1. Trim whitespace\n * 2. Convert to lowercase\n * 3. Remove common prefixes (Mr., Mrs., Dr.) for first names\n * 4. Remove common suffixes (Jr., Sr., III) for last names\n * 5. SHA-256 hash\n */\nexport async function hashName(\n name: string,\n type: 'given' | 'family' = 'given',\n): Promise<string> {\n if (!isString(name) || !name) return '';\n\n // Trim and lowercase\n let normalized = name.trim().toLowerCase();\n\n // Remove prefixes for given names\n if (type === 'given') {\n const prefixes = ['mr.', 'mrs.', 'ms.', 'miss.', 'dr.', 'prof.'];\n for (const prefix of prefixes) {\n if (normalized.startsWith(prefix)) {\n normalized = normalized.substring(prefix.length).trim();\n break;\n }\n }\n }\n\n // Remove suffixes for family names (check with and without space)\n // Sort by length (longest first) to match \"iii\" before \"ii\"\n if (type === 'family') {\n const suffixes = ['jr.', 'sr.', 'iii', 'ii', 'iv', 'v'];\n for (const suffix of suffixes) {\n // Check for suffix with space before it (e.g., \" jr.\")\n const suffixWithSpace = ` ${suffix}`;\n if (normalized.endsWith(suffixWithSpace)) {\n normalized = normalized\n .substring(0, normalized.length - suffixWithSpace.length)\n .trim();\n break;\n }\n // Check for suffix without space\n if (normalized.endsWith(suffix)) {\n normalized = normalized\n .substring(0, normalized.length - suffix.length)\n .trim();\n break;\n }\n }\n }\n\n return getHashServer(normalized);\n}\n\n/**\n * Hash multiple email addresses\n */\nexport async function hashEmails(emails: string[]): Promise<string[]> {\n return Promise.all(emails.map((email) => hashEmail(email)));\n}\n\n/**\n * Hash multiple phone numbers\n */\nexport async function hashPhones(phones: string[]): Promise<string[]> {\n return Promise.all(phones.map((phone) => hashPhone(phone)));\n}\n","export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';\n\n/* eslint-disable no-console */\nexport function createLogger(level: LogLevel = 'none') {\n const levels = { debug: 0, info: 1, warn: 2, error: 3, none: 4 };\n const currentLevel = levels[level];\n\n return {\n debug: (message: string, data?: unknown) => {\n if (currentLevel <= 0)\n console.log(`[DataManager] ${message}`, data || '');\n },\n info: (message: string, data?: unknown) => {\n if (currentLevel <= 1)\n console.log(`[DataManager] ${message}`, data || '');\n },\n warn: (message: string, data?: unknown) => {\n if (currentLevel <= 2)\n console.warn(`[DataManager] ${message}`, data || '');\n },\n error: (message: string, data?: unknown) => {\n if (currentLevel <= 3)\n console.error(`[DataManager] ${message}`, data || '');\n },\n };\n}\n/* eslint-enable no-console */\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\nimport type { LogLevel } from '../utils';\n\nexport interface Settings {\n /** OAuth 2.0 access token with datamanager scope */\n accessToken: string;\n\n /** Array of destination accounts and conversion actions/user lists */\n destinations: Destination[];\n\n /** Default event source if not specified per event */\n eventSource?: EventSource;\n\n /** Maximum number of events to batch before sending (max 2000) */\n batchSize?: number;\n\n /** Time in milliseconds to wait before auto-flushing batch */\n batchInterval?: number;\n\n /** If true, validate request without ingestion (testing mode) */\n validateOnly?: boolean;\n\n /** Override API endpoint (for testing) */\n url?: string;\n\n /** Request-level consent for all events */\n consent?: Consent;\n\n /** Test event code for debugging (optional) */\n testEventCode?: string;\n\n /** Log level for debugging (optional) */\n logLevel?: LogLevel;\n\n /** Guided helpers: User data mapping (applies to all events) */\n userData?: WalkerOSMapping.Map;\n\n /** Guided helper: First-party user ID */\n userId?: WalkerOSMapping.Value;\n\n /** Guided helper: GA4 client ID */\n clientId?: WalkerOSMapping.Value;\n\n /** Guided helper: Privacy-safe attribution (Google's sessionAttributes) */\n sessionAttributes?: WalkerOSMapping.Value;\n\n /** Consent mapping: Map consent field to adUserData (string = field name, boolean = static value) */\n consentAdUserData?: string | boolean;\n\n /** Consent mapping: Map consent field to adPersonalization (string = field name, boolean = static value) */\n consentAdPersonalization?: string | boolean;\n}\n\nexport interface Mapping {\n // Attribution identifiers (optional, for explicit mapping)\n gclid?: WalkerOSMapping.Value;\n gbraid?: WalkerOSMapping.Value;\n wbraid?: WalkerOSMapping.Value;\n sessionAttributes?: WalkerOSMapping.Value;\n}\n\nexport interface Env extends DestinationServer.Env {\n fetch?: typeof fetch;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env>;\n\nexport interface DestinationInterface\n extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n// Google Data Manager API Types\n// https://developers.google.com/data-manager/api/reference\n\n/**\n * Destination account and product identifier\n * https://developers.google.com/data-manager/api/reference/rest/v1/Destination\n */\nexport interface Destination {\n /** Operating account details */\n operatingAccount: OperatingAccount;\n\n /** Product-specific destination ID (conversion action or user list) */\n productDestinationId: string;\n}\n\n/**\n * Operating account information\n */\nexport interface OperatingAccount {\n /** Account ID (e.g., \"123-456-7890\" for Google Ads) */\n accountId: string;\n\n /** Type of account */\n accountType: AccountType;\n}\n\nexport type AccountType =\n | 'GOOGLE_ADS'\n | 'DISPLAY_VIDEO_ADVERTISER'\n | 'DISPLAY_VIDEO_PARTNER'\n | 'GOOGLE_ANALYTICS_PROPERTY';\n\nexport type EventSource = 'WEB' | 'APP' | 'IN_STORE' | 'PHONE' | 'OTHER';\n\n/**\n * Consent for Digital Markets Act (DMA) compliance\n * https://developers.google.com/data-manager/api/devguides/concepts/dma\n */\nexport interface Consent {\n /** Consent for data collection and use */\n adUserData?: ConsentStatus;\n\n /** Consent for ad personalization */\n adPersonalization?: ConsentStatus;\n}\n\nexport type ConsentStatus = 'CONSENT_GRANTED' | 'CONSENT_DENIED';\n\n/**\n * Request body for events.ingest API\n * https://developers.google.com/data-manager/api/reference/rest/v1/events/ingest\n */\nexport interface IngestEventsRequest {\n /** OAuth 2.0 access token */\n access_token?: string;\n\n /** Array of events to ingest (max 2000) */\n events: Event[];\n\n /** Array of destinations for these events (max 10) */\n destinations: Destination[];\n\n /** Request-level consent (overridden by event-level) */\n consent?: Consent;\n\n /** If true, validate without ingestion */\n validateOnly?: boolean;\n\n /** Test event code for debugging */\n testEventCode?: string;\n}\n\n/**\n * Single event for ingestion\n * https://developers.google.com/data-manager/api/reference/rest/v1/Event\n */\nexport interface Event {\n /** Event timestamp in RFC 3339 format */\n eventTimestamp: string;\n\n /** Transaction ID for deduplication (max 512 chars) */\n transactionId?: string;\n\n /** Google Analytics client ID (max 255 chars) */\n clientId?: string;\n\n /** First-party user ID (max 256 chars) */\n userId?: string;\n\n /** User data with identifiers (max 10 identifiers) */\n userData?: UserData;\n\n /** Attribution identifiers */\n adIdentifiers?: AdIdentifiers;\n\n /** Conversion value */\n conversionValue?: number;\n\n /** Currency code (ISO 4217, 3 chars) */\n currency?: string;\n\n /** Shopping cart data */\n cartData?: CartData;\n\n /** Event name for GA4 (max 40 chars, required for GA4) */\n eventName?: string;\n\n /** Source of the event */\n eventSource?: EventSource;\n\n /** Event-level consent (overrides request-level) */\n consent?: Consent;\n}\n\n/**\n * User data with identifiers\n * https://developers.google.com/data-manager/api/reference/rest/v1/UserData\n */\nexport interface UserData {\n /** Array of user identifiers (max 10) */\n userIdentifiers: UserIdentifier[];\n}\n\n/**\n * User identifier (email, phone, or address)\n */\nexport type UserIdentifier =\n | { emailAddress: string }\n | { phoneNumber: string }\n | { address: Address };\n\n/**\n * Address for user identification\n * https://developers.google.com/data-manager/api/reference/rest/v1/Address\n */\nexport interface Address {\n /** Given name (first name) - SHA-256 hashed */\n givenName?: string;\n\n /** Family name (last name) - SHA-256 hashed */\n familyName?: string;\n\n /** ISO-3166-1 alpha-2 country code - NOT hashed (e.g., \"US\", \"GB\") */\n regionCode?: string;\n\n /** Postal code - NOT hashed */\n postalCode?: string;\n}\n\n/**\n * Attribution identifiers\n * https://developers.google.com/data-manager/api/reference/rest/v1/AdIdentifiers\n */\nexport interface AdIdentifiers {\n /** Google Click ID (primary attribution) */\n gclid?: string;\n\n /** iOS attribution identifier (post-ATT) */\n gbraid?: string;\n\n /** Web-to-app attribution identifier */\n wbraid?: string;\n\n /** Session attributes (privacy-safe attribution) */\n sessionAttributes?: string;\n}\n\n/**\n * Shopping cart data\n * https://developers.google.com/data-manager/api/reference/rest/v1/CartData\n */\nexport interface CartData {\n /** Array of cart items (max 200) */\n items: CartItem[];\n}\n\n/**\n * Single cart item\n * https://developers.google.com/data-manager/api/reference/rest/v1/CartItem\n */\nexport interface CartItem {\n /** Merchant product ID (max 127 chars) */\n merchantProductId?: string;\n\n /** Item price */\n price?: number;\n\n /** Item quantity */\n quantity?: number;\n}\n\n/**\n * Response from events.ingest API\n * https://developers.google.com/data-manager/api/reference/rest/v1/IngestEventsResponse\n */\nexport interface IngestEventsResponse {\n /** Unique request ID for status checking */\n requestId: string;\n\n /** Validation errors (only if validateOnly=true) */\n validationErrors?: ValidationError[];\n}\n\n/**\n * Validation error\n */\nexport interface ValidationError {\n /** Error code */\n code: string;\n\n /** Human-readable error message */\n message: string;\n\n /** Field path that caused the error */\n fieldPath?: string;\n}\n\n/**\n * Request status response\n * https://developers.google.com/data-manager/api/reference/rest/v1/requestStatus/retrieve\n */\nexport interface RequestStatusResponse {\n /** Unique request ID */\n requestId: string;\n\n /** Processing state */\n state: RequestState;\n\n /** Number of events successfully ingested */\n eventsIngested?: number;\n\n /** Number of events that failed */\n eventsFailed?: number;\n\n /** Array of errors (if any) */\n errors?: RequestError[];\n}\n\nexport type RequestState =\n | 'STATE_UNSPECIFIED'\n | 'PENDING'\n | 'PROCESSING'\n | 'SUCCEEDED'\n | 'FAILED'\n | 'PARTIALLY_SUCCEEDED';\n\n/**\n * Request error\n */\nexport interface RequestError {\n /** Error code */\n code: string;\n\n /** Human-readable error message */\n message: string;\n\n /** Number of events affected by this error */\n eventCount?: number;\n}\n","import type { DestinationInterface } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationDataManager from './types';\n\nexport const destinationDataManager: DestinationInterface = {\n type: 'datamanager',\n\n config: {},\n\n async init({ config: partialConfig }) {\n const config = getConfig(partialConfig);\n return config;\n },\n\n async push(event, { config, mapping, data, collector, env }) {\n return await push(event, { config, mapping, data, collector, env });\n },\n};\n\nexport default destinationDataManager;\n"],"mappings":"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","names":["isString","isString"]}
|
package/dist/schemas.d.mts
CHANGED
package/dist/schemas.d.ts
CHANGED
package/dist/schemas.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,o=Object.defineProperty,n=Object.getOwnPropertyDescriptor,t=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,r={};((e,n)=>{for(var t in n)o(e,t,{get:n[t],enumerable:!0})})(r,{schemas:()=>
|
|
1
|
+
"use strict";var e,o=Object.defineProperty,n=Object.getOwnPropertyDescriptor,t=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,r={};((e,n)=>{for(var t in n)o(e,t,{get:n[t],enumerable:!0})})(r,{schemas:()=>v}),module.exports=(e=r,((e,r,a,s)=>{if(r&&"object"==typeof r||"function"==typeof r)for(let c of t(r))i.call(e,c)||c===a||o(e,c,{get:()=>r[c],enumerable:!(s=n(r,c))||s.enumerable});return e})(o({},"__esModule",{value:!0}),e));var a=require("@walkeros/core/dev"),s=a.z.enum(["GOOGLE_ADS","DISPLAY_VIDEO_ADVERTISER","DISPLAY_VIDEO_PARTNER","GOOGLE_ANALYTICS_PROPERTY"]),c=a.z.enum(["WEB","APP","IN_STORE","PHONE","OTHER"]),l=a.z.enum(["CONSENT_GRANTED","CONSENT_DENIED"]),d=a.z.object({adUserData:l.describe("Consent for data collection and use").optional(),adPersonalization:l.describe("Consent for ad personalization").optional()}),u=a.z.object({accountId:a.z.string().min(1).describe('Account ID (e.g., "123-456-7890" for Google Ads)'),accountType:s.describe("Type of account")}),b=a.z.object({operatingAccount:u.describe("Operating account details"),productDestinationId:a.z.string().min(1).describe("Product-specific destination ID (conversion action or user list)")}),p=require("@walkeros/core/dev"),g=p.z.object({accessToken:p.z.string().min(1).describe("OAuth 2.0 access token with datamanager scope (like ya29.c.xxx)"),destinations:p.z.array(b).min(1).max(10).describe("Array of destination accounts and conversion actions/user lists (max 10)"),eventSource:c.describe("Default event source if not specified per event (like WEB)").optional(),batchSize:p.z.number().int().min(1).max(2e3).describe("Maximum number of events to batch before sending (max 2000, like 100)").optional(),batchInterval:p.z.number().int().min(0).describe("Time in milliseconds to wait before auto-flushing batch (like 5000)").optional(),validateOnly:p.z.boolean().describe("If true, validate request without ingestion (testing mode)").optional(),url:p.z.string().url().describe("Override API endpoint for testing (like https://datamanager.googleapis.com/v1)").optional(),consent:d.describe("Request-level consent for all events").optional(),testEventCode:p.z.string().describe("Test event code for debugging (like TEST12345)").optional(),logLevel:p.z.enum(["debug","info","warn","error","none"]).describe("Log level for debugging (debug shows all API calls)").optional(),userData:p.z.record(p.z.string(),p.z.unknown()).describe("Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })").optional(),userId:p.z.any().describe("Guided helper: First-party user ID for all events (like 'user.id')").optional(),clientId:p.z.any().describe("Guided helper: GA4 client ID for all events (like 'user.device')").optional(),sessionAttributes:p.z.any().describe("Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')").optional(),consentAdUserData:p.z.union([p.z.string(),p.z.boolean()]).describe("Consent mapping: Field name from event.consent (like 'marketing') or static boolean value").optional(),consentAdPersonalization:p.z.union([p.z.string(),p.z.boolean()]).describe("Consent mapping: Field name from event.consent (like 'targeting') or static boolean value").optional()}),m=require("@walkeros/core/dev").z.object({}),z=require("@walkeros/core/dev"),v={settings:(0,z.zodToSchema)(g),mapping:(0,z.zodToSchema)(m)};//# sourceMappingURL=schemas.js.map
|
package/dist/schemas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas.ts","../src/schemas/primitives.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/index.ts"],"sourcesContent":["// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nimport { schemas } from './schemas/index';\n\nexport { schemas };\n","import { z } from '@walkeros/core';\n\nexport const AccountTypeSchema = z.enum([\n 'GOOGLE_ADS',\n 'DISPLAY_VIDEO_ADVERTISER',\n 'DISPLAY_VIDEO_PARTNER',\n 'GOOGLE_ANALYTICS_PROPERTY',\n]);\n\nexport const EventSourceSchema = z.enum([\n 'WEB',\n 'APP',\n 'IN_STORE',\n 'PHONE',\n 'OTHER',\n]);\n\nexport const ConsentStatusSchema = z.enum([\n 'CONSENT_GRANTED',\n 'CONSENT_DENIED',\n]);\n\nexport const ConsentSchema = z.object({\n adUserData: ConsentStatusSchema.describe(\n 'Consent for data collection and use',\n ).optional(),\n adPersonalization: ConsentStatusSchema.describe(\n 'Consent for ad personalization',\n ).optional(),\n});\n\nexport const OperatingAccountSchema = z.object({\n accountId: z\n .string()\n .min(1)\n .describe('Account ID (e.g., \"123-456-7890\" for Google Ads)'),\n accountType: AccountTypeSchema.describe('Type of account'),\n});\n\nexport const DestinationSchema = z.object({\n operatingAccount: OperatingAccountSchema.describe(\n 'Operating account details',\n ),\n productDestinationId: z\n .string()\n .min(1)\n .describe(\n 'Product-specific destination ID (conversion action or user list)',\n ),\n});\n","import { z } from '@walkeros/core';\nimport {\n DestinationSchema,\n EventSourceSchema,\n ConsentSchema,\n} from './primitives';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'OAuth 2.0 access token with datamanager scope (like ya29.c.xxx)',\n ),\n destinations: z\n .array(DestinationSchema)\n .min(1)\n .max(10)\n .describe(\n 'Array of destination accounts and conversion actions/user lists (max 10)',\n ),\n eventSource: EventSourceSchema.describe(\n 'Default event source if not specified per event (like WEB)',\n ).optional(),\n batchSize: z\n .number()\n .int()\n .min(1)\n .max(2000)\n .describe(\n 'Maximum number of events to batch before sending (max 2000, like 100)',\n )\n .optional(),\n batchInterval: z\n .number()\n .int()\n .min(0)\n .describe(\n 'Time in milliseconds to wait before auto-flushing batch (like 5000)',\n )\n .optional(),\n validateOnly: z\n .boolean()\n .describe('If true, validate request without ingestion (testing mode)')\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Override API endpoint for testing (like https://datamanager.googleapis.com/v1)',\n )\n .optional(),\n consent: ConsentSchema.describe(\n 'Request-level consent for all events',\n ).optional(),\n testEventCode: z\n .string()\n .describe('Test event code for debugging (like TEST12345)')\n .optional(),\n logLevel: z\n .enum(['debug', 'info', 'warn', 'error', 'none'])\n .describe('Log level for debugging (debug shows all API calls)')\n .optional(),\n userData: z\n .record(z.string(), z.unknown())\n .describe(\n \"Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })\",\n )\n .optional(),\n userId: z\n .any()\n .describe(\n \"Guided helper: First-party user ID for all events (like 'user.id')\",\n )\n .optional(),\n clientId: z\n .any()\n .describe(\n \"Guided helper: GA4 client ID for all events (like 'user.device')\",\n )\n .optional(),\n sessionAttributes: z\n .any()\n .describe(\n \"Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')\",\n )\n .optional(),\n consentAdUserData: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'marketing') or static boolean value\",\n )\n .optional(),\n consentAdPersonalization: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'targeting') or static boolean value\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core';\n\n// Data Manager uses flexible mapping via walkerOS mapping system\n// No event-specific mapping schema needed (similar to Meta CAPI pattern)\nexport const MappingSchema = z.object({});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * from './primitives';\nexport * from './settings';\nexport * from './mapping';\n\nimport { zodToSchema } from '@walkeros/core';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nimport type { JSONSchema } from '@walkeros/core';\n\nexport const schemas: Record<string, JSONSchema> = {\n settings: zodToSchema(SettingsSchema),\n mapping: zodToSchema(MappingSchema),\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,
|
|
1
|
+
{"version":3,"sources":["../src/schemas.ts","../src/schemas/primitives.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/index.ts"],"sourcesContent":["// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nimport { schemas } from './schemas/index';\n\nexport { schemas };\n","import { z } from '@walkeros/core/dev';\n\nexport const AccountTypeSchema = z.enum([\n 'GOOGLE_ADS',\n 'DISPLAY_VIDEO_ADVERTISER',\n 'DISPLAY_VIDEO_PARTNER',\n 'GOOGLE_ANALYTICS_PROPERTY',\n]);\n\nexport const EventSourceSchema = z.enum([\n 'WEB',\n 'APP',\n 'IN_STORE',\n 'PHONE',\n 'OTHER',\n]);\n\nexport const ConsentStatusSchema = z.enum([\n 'CONSENT_GRANTED',\n 'CONSENT_DENIED',\n]);\n\nexport const ConsentSchema = z.object({\n adUserData: ConsentStatusSchema.describe(\n 'Consent for data collection and use',\n ).optional(),\n adPersonalization: ConsentStatusSchema.describe(\n 'Consent for ad personalization',\n ).optional(),\n});\n\nexport const OperatingAccountSchema = z.object({\n accountId: z\n .string()\n .min(1)\n .describe('Account ID (e.g., \"123-456-7890\" for Google Ads)'),\n accountType: AccountTypeSchema.describe('Type of account'),\n});\n\nexport const DestinationSchema = z.object({\n operatingAccount: OperatingAccountSchema.describe(\n 'Operating account details',\n ),\n productDestinationId: z\n .string()\n .min(1)\n .describe(\n 'Product-specific destination ID (conversion action or user list)',\n ),\n});\n","import { z } from '@walkeros/core/dev';\nimport {\n DestinationSchema,\n EventSourceSchema,\n ConsentSchema,\n} from './primitives';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'OAuth 2.0 access token with datamanager scope (like ya29.c.xxx)',\n ),\n destinations: z\n .array(DestinationSchema)\n .min(1)\n .max(10)\n .describe(\n 'Array of destination accounts and conversion actions/user lists (max 10)',\n ),\n eventSource: EventSourceSchema.describe(\n 'Default event source if not specified per event (like WEB)',\n ).optional(),\n batchSize: z\n .number()\n .int()\n .min(1)\n .max(2000)\n .describe(\n 'Maximum number of events to batch before sending (max 2000, like 100)',\n )\n .optional(),\n batchInterval: z\n .number()\n .int()\n .min(0)\n .describe(\n 'Time in milliseconds to wait before auto-flushing batch (like 5000)',\n )\n .optional(),\n validateOnly: z\n .boolean()\n .describe('If true, validate request without ingestion (testing mode)')\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Override API endpoint for testing (like https://datamanager.googleapis.com/v1)',\n )\n .optional(),\n consent: ConsentSchema.describe(\n 'Request-level consent for all events',\n ).optional(),\n testEventCode: z\n .string()\n .describe('Test event code for debugging (like TEST12345)')\n .optional(),\n logLevel: z\n .enum(['debug', 'info', 'warn', 'error', 'none'])\n .describe('Log level for debugging (debug shows all API calls)')\n .optional(),\n userData: z\n .record(z.string(), z.unknown())\n .describe(\n \"Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })\",\n )\n .optional(),\n userId: z\n .any()\n .describe(\n \"Guided helper: First-party user ID for all events (like 'user.id')\",\n )\n .optional(),\n clientId: z\n .any()\n .describe(\n \"Guided helper: GA4 client ID for all events (like 'user.device')\",\n )\n .optional(),\n sessionAttributes: z\n .any()\n .describe(\n \"Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')\",\n )\n .optional(),\n consentAdUserData: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'marketing') or static boolean value\",\n )\n .optional(),\n consentAdPersonalization: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'targeting') or static boolean value\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n// Data Manager uses flexible mapping via walkerOS mapping system\n// No event-specific mapping schema needed (similar to Meta CAPI pattern)\nexport const MappingSchema = z.object({});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * from './primitives';\nexport * from './settings';\nexport * from './mapping';\n\nimport { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nimport type { JSONSchema } from '@walkeros/core/dev';\n\nexport const schemas: Record<string, JSONSchema> = {\n settings: zodToSchema(SettingsSchema),\n mapping: zodToSchema(MappingSchema),\n};\n"],"mappings":"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","names":["import_dev","import_dev","import_dev"]}
|
package/dist/schemas.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as e}from"@walkeros/core";var n=e.enum(["GOOGLE_ADS","DISPLAY_VIDEO_ADVERTISER","DISPLAY_VIDEO_PARTNER","GOOGLE_ANALYTICS_PROPERTY"]),o=e.enum(["WEB","APP","IN_STORE","PHONE","OTHER"]),i=e.enum(["CONSENT_GRANTED","CONSENT_DENIED"]),t=e.object({adUserData:i.describe("Consent for data collection and use").optional(),adPersonalization:i.describe("Consent for ad personalization").optional()}),a=e.object({accountId:e.string().min(1).describe('Account ID (e.g., "123-456-7890" for Google Ads)'),accountType:n.describe("Type of account")}),r=e.object({operatingAccount:a.describe("Operating account details"),productDestinationId:e.string().min(1).describe("Product-specific destination ID (conversion action or user list)")});import{z as s}from"@walkeros/core";var l=s.object({accessToken:s.string().min(1).describe("OAuth 2.0 access token with datamanager scope (like ya29.c.xxx)"),destinations:s.array(r).min(1).max(10).describe("Array of destination accounts and conversion actions/user lists (max 10)"),eventSource:o.describe("Default event source if not specified per event (like WEB)").optional(),batchSize:s.number().int().min(1).max(2e3).describe("Maximum number of events to batch before sending (max 2000, like 100)").optional(),batchInterval:s.number().int().min(0).describe("Time in milliseconds to wait before auto-flushing batch (like 5000)").optional(),validateOnly:s.boolean().describe("If true, validate request without ingestion (testing mode)").optional(),url:s.string().url().describe("Override API endpoint for testing (like https://datamanager.googleapis.com/v1)").optional(),consent:t.describe("Request-level consent for all events").optional(),testEventCode:s.string().describe("Test event code for debugging (like TEST12345)").optional(),logLevel:s.enum(["debug","info","warn","error","none"]).describe("Log level for debugging (debug shows all API calls)").optional(),userData:s.record(s.string(),s.unknown()).describe("Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })").optional(),userId:s.any().describe("Guided helper: First-party user ID for all events (like 'user.id')").optional(),clientId:s.any().describe("Guided helper: GA4 client ID for all events (like 'user.device')").optional(),sessionAttributes:s.any().describe("Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')").optional(),consentAdUserData:s.union([s.string(),s.boolean()]).describe("Consent mapping: Field name from event.consent (like 'marketing') or static boolean value").optional(),consentAdPersonalization:s.union([s.string(),s.boolean()]).describe("Consent mapping: Field name from event.consent (like 'targeting') or static boolean value").optional()});import{z as c}from"@walkeros/core";var d=c.object({});import{zodToSchema as u}from"@walkeros/core";var p={settings:u(l),mapping:u(d)};export{p as schemas};//# sourceMappingURL=schemas.mjs.map
|
|
1
|
+
import{z as e}from"@walkeros/core/dev";var n=e.enum(["GOOGLE_ADS","DISPLAY_VIDEO_ADVERTISER","DISPLAY_VIDEO_PARTNER","GOOGLE_ANALYTICS_PROPERTY"]),o=e.enum(["WEB","APP","IN_STORE","PHONE","OTHER"]),i=e.enum(["CONSENT_GRANTED","CONSENT_DENIED"]),t=e.object({adUserData:i.describe("Consent for data collection and use").optional(),adPersonalization:i.describe("Consent for ad personalization").optional()}),a=e.object({accountId:e.string().min(1).describe('Account ID (e.g., "123-456-7890" for Google Ads)'),accountType:n.describe("Type of account")}),r=e.object({operatingAccount:a.describe("Operating account details"),productDestinationId:e.string().min(1).describe("Product-specific destination ID (conversion action or user list)")});import{z as s}from"@walkeros/core/dev";var l=s.object({accessToken:s.string().min(1).describe("OAuth 2.0 access token with datamanager scope (like ya29.c.xxx)"),destinations:s.array(r).min(1).max(10).describe("Array of destination accounts and conversion actions/user lists (max 10)"),eventSource:o.describe("Default event source if not specified per event (like WEB)").optional(),batchSize:s.number().int().min(1).max(2e3).describe("Maximum number of events to batch before sending (max 2000, like 100)").optional(),batchInterval:s.number().int().min(0).describe("Time in milliseconds to wait before auto-flushing batch (like 5000)").optional(),validateOnly:s.boolean().describe("If true, validate request without ingestion (testing mode)").optional(),url:s.string().url().describe("Override API endpoint for testing (like https://datamanager.googleapis.com/v1)").optional(),consent:t.describe("Request-level consent for all events").optional(),testEventCode:s.string().describe("Test event code for debugging (like TEST12345)").optional(),logLevel:s.enum(["debug","info","warn","error","none"]).describe("Log level for debugging (debug shows all API calls)").optional(),userData:s.record(s.string(),s.unknown()).describe("Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })").optional(),userId:s.any().describe("Guided helper: First-party user ID for all events (like 'user.id')").optional(),clientId:s.any().describe("Guided helper: GA4 client ID for all events (like 'user.device')").optional(),sessionAttributes:s.any().describe("Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')").optional(),consentAdUserData:s.union([s.string(),s.boolean()]).describe("Consent mapping: Field name from event.consent (like 'marketing') or static boolean value").optional(),consentAdPersonalization:s.union([s.string(),s.boolean()]).describe("Consent mapping: Field name from event.consent (like 'targeting') or static boolean value").optional()});import{z as c}from"@walkeros/core/dev";var d=c.object({});import{zodToSchema as u}from"@walkeros/core/dev";var p={settings:u(l),mapping:u(d)};export{p as schemas};//# sourceMappingURL=schemas.mjs.map
|
package/dist/schemas.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas/primitives.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/index.ts"],"sourcesContent":["import { z } from '@walkeros/core';\n\nexport const AccountTypeSchema = z.enum([\n 'GOOGLE_ADS',\n 'DISPLAY_VIDEO_ADVERTISER',\n 'DISPLAY_VIDEO_PARTNER',\n 'GOOGLE_ANALYTICS_PROPERTY',\n]);\n\nexport const EventSourceSchema = z.enum([\n 'WEB',\n 'APP',\n 'IN_STORE',\n 'PHONE',\n 'OTHER',\n]);\n\nexport const ConsentStatusSchema = z.enum([\n 'CONSENT_GRANTED',\n 'CONSENT_DENIED',\n]);\n\nexport const ConsentSchema = z.object({\n adUserData: ConsentStatusSchema.describe(\n 'Consent for data collection and use',\n ).optional(),\n adPersonalization: ConsentStatusSchema.describe(\n 'Consent for ad personalization',\n ).optional(),\n});\n\nexport const OperatingAccountSchema = z.object({\n accountId: z\n .string()\n .min(1)\n .describe('Account ID (e.g., \"123-456-7890\" for Google Ads)'),\n accountType: AccountTypeSchema.describe('Type of account'),\n});\n\nexport const DestinationSchema = z.object({\n operatingAccount: OperatingAccountSchema.describe(\n 'Operating account details',\n ),\n productDestinationId: z\n .string()\n .min(1)\n .describe(\n 'Product-specific destination ID (conversion action or user list)',\n ),\n});\n","import { z } from '@walkeros/core';\nimport {\n DestinationSchema,\n EventSourceSchema,\n ConsentSchema,\n} from './primitives';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'OAuth 2.0 access token with datamanager scope (like ya29.c.xxx)',\n ),\n destinations: z\n .array(DestinationSchema)\n .min(1)\n .max(10)\n .describe(\n 'Array of destination accounts and conversion actions/user lists (max 10)',\n ),\n eventSource: EventSourceSchema.describe(\n 'Default event source if not specified per event (like WEB)',\n ).optional(),\n batchSize: z\n .number()\n .int()\n .min(1)\n .max(2000)\n .describe(\n 'Maximum number of events to batch before sending (max 2000, like 100)',\n )\n .optional(),\n batchInterval: z\n .number()\n .int()\n .min(0)\n .describe(\n 'Time in milliseconds to wait before auto-flushing batch (like 5000)',\n )\n .optional(),\n validateOnly: z\n .boolean()\n .describe('If true, validate request without ingestion (testing mode)')\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Override API endpoint for testing (like https://datamanager.googleapis.com/v1)',\n )\n .optional(),\n consent: ConsentSchema.describe(\n 'Request-level consent for all events',\n ).optional(),\n testEventCode: z\n .string()\n .describe('Test event code for debugging (like TEST12345)')\n .optional(),\n logLevel: z\n .enum(['debug', 'info', 'warn', 'error', 'none'])\n .describe('Log level for debugging (debug shows all API calls)')\n .optional(),\n userData: z\n .record(z.string(), z.unknown())\n .describe(\n \"Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })\",\n )\n .optional(),\n userId: z\n .any()\n .describe(\n \"Guided helper: First-party user ID for all events (like 'user.id')\",\n )\n .optional(),\n clientId: z\n .any()\n .describe(\n \"Guided helper: GA4 client ID for all events (like 'user.device')\",\n )\n .optional(),\n sessionAttributes: z\n .any()\n .describe(\n \"Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')\",\n )\n .optional(),\n consentAdUserData: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'marketing') or static boolean value\",\n )\n .optional(),\n consentAdPersonalization: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'targeting') or static boolean value\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core';\n\n// Data Manager uses flexible mapping via walkerOS mapping system\n// No event-specific mapping schema needed (similar to Meta CAPI pattern)\nexport const MappingSchema = z.object({});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * from './primitives';\nexport * from './settings';\nexport * from './mapping';\n\nimport { zodToSchema } from '@walkeros/core';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nimport type { JSONSchema } from '@walkeros/core';\n\nexport const schemas: Record<string, JSONSchema> = {\n settings: zodToSchema(SettingsSchema),\n mapping: zodToSchema(MappingSchema),\n};\n"],"mappings":";AAAA,SAAS,SAAS;AAEX,IAAM,oBAAoB,EAAE,KAAK;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,oBAAoB,EAAE,KAAK;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,sBAAsB,EAAE,KAAK;AAAA,EACxC;AAAA,EACA;AACF,CAAC;AAEM,IAAM,gBAAgB,EAAE,OAAO;AAAA,EACpC,YAAY,oBAAoB;AAAA,IAC9B;AAAA,EACF,EAAE,SAAS;AAAA,EACX,mBAAmB,oBAAoB;AAAA,IACrC;AAAA,EACF,EAAE,SAAS;AACb,CAAC;AAEM,IAAM,yBAAyB,EAAE,OAAO;AAAA,EAC7C,WAAW,EACR,OAAO,EACP,IAAI,CAAC,EACL,SAAS,kDAAkD;AAAA,EAC9D,aAAa,kBAAkB,SAAS,iBAAiB;AAC3D,CAAC;AAEM,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,kBAAkB,uBAAuB;AAAA,IACvC;AAAA,EACF;AAAA,EACA,sBAAsB,EACnB,OAAO,EACP,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF;AACJ,CAAC;;;ACjDD,SAAS,KAAAA,UAAS;AAOX,IAAM,iBAAiBC,GAAE,OAAO;AAAA,EACrC,aAAaA,GACV,OAAO,EACP,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF;AAAA,EACF,cAAcA,GACX,MAAM,iBAAiB,EACvB,IAAI,CAAC,EACL,IAAI,EAAE,EACN;AAAA,IACC;AAAA,EACF;AAAA,EACF,aAAa,kBAAkB;AAAA,IAC7B;AAAA,EACF,EAAE,SAAS;AAAA,EACX,WAAWA,GACR,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,GAAI,EACR;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,eAAeA,GACZ,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,cAAcA,GACX,QAAQ,EACR,SAAS,4DAA4D,EACrE,SAAS;AAAA,EACZ,KAAKA,GACF,OAAO,EACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,SAAS,cAAc;AAAA,IACrB;AAAA,EACF,EAAE,SAAS;AAAA,EACX,eAAeA,GACZ,OAAO,EACP,SAAS,gDAAgD,EACzD,SAAS;AAAA,EACZ,UAAUA,GACP,KAAK,CAAC,SAAS,QAAQ,QAAQ,SAAS,MAAM,CAAC,EAC/C,SAAS,qDAAqD,EAC9D,SAAS;AAAA,EACZ,UAAUA,GACP,OAAOA,GAAE,OAAO,GAAGA,GAAE,QAAQ,CAAC,EAC9B;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,QAAQA,GACL,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,UAAUA,GACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,mBAAmBA,GAChB,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,mBAAmBA,GAChB,MAAM,CAACA,GAAE,OAAO,GAAGA,GAAE,QAAQ,CAAC,CAAC,EAC/B;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,0BAA0BA,GACvB,MAAM,CAACA,GAAE,OAAO,GAAGA,GAAE,QAAQ,CAAC,CAAC,EAC/B;AAAA,IACC;AAAA,EACF,EACC,SAAS;AACd,CAAC;;;ACnGD,SAAS,KAAAC,UAAS;AAIX,IAAM,gBAAgBA,GAAE,OAAO,CAAC,CAAC;;;ACAxC,SAAS,mBAAmB;AAMrB,IAAM,UAAsC;AAAA,EACjD,UAAU,YAAY,cAAc;AAAA,EACpC,SAAS,YAAY,aAAa;AACpC;","names":["z","z","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/schemas/primitives.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/index.ts"],"sourcesContent":["import { z } from '@walkeros/core/dev';\n\nexport const AccountTypeSchema = z.enum([\n 'GOOGLE_ADS',\n 'DISPLAY_VIDEO_ADVERTISER',\n 'DISPLAY_VIDEO_PARTNER',\n 'GOOGLE_ANALYTICS_PROPERTY',\n]);\n\nexport const EventSourceSchema = z.enum([\n 'WEB',\n 'APP',\n 'IN_STORE',\n 'PHONE',\n 'OTHER',\n]);\n\nexport const ConsentStatusSchema = z.enum([\n 'CONSENT_GRANTED',\n 'CONSENT_DENIED',\n]);\n\nexport const ConsentSchema = z.object({\n adUserData: ConsentStatusSchema.describe(\n 'Consent for data collection and use',\n ).optional(),\n adPersonalization: ConsentStatusSchema.describe(\n 'Consent for ad personalization',\n ).optional(),\n});\n\nexport const OperatingAccountSchema = z.object({\n accountId: z\n .string()\n .min(1)\n .describe('Account ID (e.g., \"123-456-7890\" for Google Ads)'),\n accountType: AccountTypeSchema.describe('Type of account'),\n});\n\nexport const DestinationSchema = z.object({\n operatingAccount: OperatingAccountSchema.describe(\n 'Operating account details',\n ),\n productDestinationId: z\n .string()\n .min(1)\n .describe(\n 'Product-specific destination ID (conversion action or user list)',\n ),\n});\n","import { z } from '@walkeros/core/dev';\nimport {\n DestinationSchema,\n EventSourceSchema,\n ConsentSchema,\n} from './primitives';\n\nexport const SettingsSchema = z.object({\n accessToken: z\n .string()\n .min(1)\n .describe(\n 'OAuth 2.0 access token with datamanager scope (like ya29.c.xxx)',\n ),\n destinations: z\n .array(DestinationSchema)\n .min(1)\n .max(10)\n .describe(\n 'Array of destination accounts and conversion actions/user lists (max 10)',\n ),\n eventSource: EventSourceSchema.describe(\n 'Default event source if not specified per event (like WEB)',\n ).optional(),\n batchSize: z\n .number()\n .int()\n .min(1)\n .max(2000)\n .describe(\n 'Maximum number of events to batch before sending (max 2000, like 100)',\n )\n .optional(),\n batchInterval: z\n .number()\n .int()\n .min(0)\n .describe(\n 'Time in milliseconds to wait before auto-flushing batch (like 5000)',\n )\n .optional(),\n validateOnly: z\n .boolean()\n .describe('If true, validate request without ingestion (testing mode)')\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Override API endpoint for testing (like https://datamanager.googleapis.com/v1)',\n )\n .optional(),\n consent: ConsentSchema.describe(\n 'Request-level consent for all events',\n ).optional(),\n testEventCode: z\n .string()\n .describe('Test event code for debugging (like TEST12345)')\n .optional(),\n logLevel: z\n .enum(['debug', 'info', 'warn', 'error', 'none'])\n .describe('Log level for debugging (debug shows all API calls)')\n .optional(),\n userData: z\n .record(z.string(), z.unknown())\n .describe(\n \"Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })\",\n )\n .optional(),\n userId: z\n .any()\n .describe(\n \"Guided helper: First-party user ID for all events (like 'user.id')\",\n )\n .optional(),\n clientId: z\n .any()\n .describe(\n \"Guided helper: GA4 client ID for all events (like 'user.device')\",\n )\n .optional(),\n sessionAttributes: z\n .any()\n .describe(\n \"Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')\",\n )\n .optional(),\n consentAdUserData: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'marketing') or static boolean value\",\n )\n .optional(),\n consentAdPersonalization: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'targeting') or static boolean value\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n// Data Manager uses flexible mapping via walkerOS mapping system\n// No event-specific mapping schema needed (similar to Meta CAPI pattern)\nexport const MappingSchema = z.object({});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * from './primitives';\nexport * from './settings';\nexport * from './mapping';\n\nimport { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nimport type { JSONSchema } from '@walkeros/core/dev';\n\nexport const schemas: Record<string, JSONSchema> = {\n settings: zodToSchema(SettingsSchema),\n mapping: zodToSchema(MappingSchema),\n};\n"],"mappings":"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","names":["z","z","z"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walkeros/server-destination-datamanager",
|
|
3
3
|
"description": "Google Data Manager server destination for walkerOS",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
"import": "./dist/index.mjs",
|
|
10
10
|
"require": "./dist/index.js"
|
|
11
11
|
},
|
|
12
|
-
"./
|
|
13
|
-
"types": "./dist/schemas.d.ts",
|
|
14
|
-
"import": "./dist/schemas.mjs",
|
|
15
|
-
"require": "./dist/schemas.js"
|
|
12
|
+
"./dev": {
|
|
13
|
+
"types": "./dist/schemas-entry.d.ts",
|
|
14
|
+
"import": "./dist/schemas-entry.mjs",
|
|
15
|
+
"require": "./dist/schemas-entry.js"
|
|
16
16
|
},
|
|
17
17
|
"./examples": {
|
|
18
18
|
"types": "./dist/examples/index.d.ts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"update": "npx npm-check-updates -u && npm update"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@walkeros/core": "0.
|
|
36
|
-
"@walkeros/server-core": "0.
|
|
35
|
+
"@walkeros/core": "0.4.0",
|
|
36
|
+
"@walkeros/server-core": "0.4.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {},
|
|
39
39
|
"repository": {
|