@walkeros/server-destination-mparticle 4.0.0-next-1777463920154 → 4.0.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/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,o={};((e,n)=>{for(var i in n)t(e,i,{get:n[i],enumerable:!0})})(o,{DestinationMParticle:()=>m,default:()=>v,destinationMParticle:()=>g}),module.exports=(e=o,((e,o,r,c)=>{if(o&&"object"==typeof o||"function"==typeof o)for(let a of i(o))s.call(e,a)||a===r||t(e,a,{get:()=>o[a],enumerable:!(c=n(o,a))||c.enumerable});return e})(t({},"__esModule",{value:!0}),e));var r=require("@walkeros/core"),c=require("@walkeros/server-core");var a=async function(e,{config:t,rule:n,data:i,env:s,logger:o}){const a=t.settings,{apiKey:m,apiSecret:g,pod:v="us1",environment:d="production",userIdentities:l,userAttributes:f,consent:y,ip:b,sourceRequestId:_}=a,O=n?.settings||{},j=(0,r.isObject)(i)?i:{},w=await async function(e,t,n){const i={...(0,r.isObject)(t)?t:{},...(0,r.isObject)(n)?n:{}},s=Object.keys(i);if(0===s.length)return;const o={};for(const t of s){const n=p(await(0,r.getMappingValue)(e,i[t]));void 0!==n&&(o[t]=n)}return Object.keys(o).length>0?o:void 0}(e,l,O.userIdentities),h=await async function(e,t,n){const i=t?await(0,r.getMappingValue)(e,t):void 0,s=n?await(0,r.getMappingValue)(e,n):void 0,o={...(0,r.isObject)(i)?i:{},...(0,r.isObject)(s)?s:{}};return Object.keys(o).length>0?o:void 0}(e,f,O.userAttributes),k=b?u(await(0,r.getMappingValue)(e,b)):void 0,P=u(_?await(0,r.getMappingValue)(e,_):void 0)??(e.id||void 0),S=n?.name||e.name,I=e.timestamp||Date.now(),M=e.id||void 0,q=O.eventType||"custom_event";let x;if("screen_view"===q)x=function(e,t,n,i){return{event_type:"screen_view",data:{...e?{screen_name:e}:{},...t&&Object.keys(t).length>0?{custom_attributes:t}:{},...void 0!==n?{timestamp_unixtime_ms:n}:{},...i?{source_message_id:i}:{}}}}(S,j,I,M);else if("commerce_event"===q){const t=O.commerce?await(0,r.getMappingValue)(e,O.commerce):void 0;x=function(e,t,n,i){return{event_type:"commerce_event",data:{...e||{},...t&&Object.keys(t).length>0?{custom_attributes:t}:{},...void 0!==n?{timestamp_unixtime_ms:n}:{},...i?{source_message_id:i}:{}}}}((0,r.isObject)(t)?t:void 0,j,I,M)}else{x=function(e,t,n,i,s){return{event_type:"custom_event",data:{event_name:e,custom_event_type:t,...n&&Object.keys(n).length>0?{custom_attributes:n}:{},...void 0!==i?{timestamp_unixtime_ms:i}:{},...s?{source_message_id:s}:{}}}}(S,O.customEventType||"other",j,I,M)}const A=function(e,t,n,i,s={}){const o={events:e,environment:i};return t&&Object.keys(t).length>0&&(o.user_identities=t),n&&Object.keys(n).length>0&&(o.user_attributes=n),s.ip&&(o.ip=s.ip),s.sourceRequestId&&(o.source_request_id=s.sourceRequestId),s.consent&&(o.consent_state=s.consent),s.context&&(o.context=s.context),o}([x],w,h,d,{ip:k,sourceRequestId:P,consent:y}),V=function(e="us1"){return"us1"===e?"https://s2s.mparticle.com/v2/events":`https://s2s.${e}.mparticle.com/v2/events`}(v),T=function(e,t){return`Basic ${Buffer.from(`${e}:${t}`).toString("base64")}`}(m,g);o.debug("Calling mParticle Events API",{endpoint:V,method:"POST",eventType:x.event_type,eventName:S,eventId:e.id});const $=s?.sendServer||c.sendServer,C=await $(V,JSON.stringify(A),{headers:{Authorization:T,"Content-Type":"application/json"}});o.debug("mParticle API response",{ok:!(0,r.isObject)(C)||C.ok}),(0,r.isObject)(C)&&!1===C.ok&&o.throw(`mParticle API error: ${JSON.stringify(C)}`)};function u(e){if(null!=e)return"string"==typeof e?e||void 0:"number"==typeof e||"boolean"==typeof e?String(e):void 0}function p(e){if(null!=e)return"string"==typeof e?e||void 0:"number"==typeof e?e:"boolean"==typeof e?String(e):void 0}var m={},g={type:"mparticle",config:{},async init({config:e,logger:t}){const n=function(e={},t){const n=e.settings||{},{apiKey:i,apiSecret:s}=n;i||t.throw("Config settings apiKey missing"),s||t.throw("Config settings apiSecret missing");const o={pod:"us1",environment:"production",...n,apiKey:i,apiSecret:s};return{...e,settings:o}}(e,t);return n},push:async(e,t)=>await a(e,t)},v=g;//# sourceMappingURL=index.js.map
1
+ "use strict";var e,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,s={};((e,n)=>{for(var i in n)t(e,i,{get:n[i],enumerable:!0})})(s,{DestinationMParticle:()=>l,default:()=>g,destinationMParticle:()=>m}),module.exports=(e=s,((e,s,r,c)=>{if(s&&"object"==typeof s||"function"==typeof s)for(let a of i(s))o.call(e,a)||a===r||t(e,a,{get:()=>s[a],enumerable:!(c=n(s,a))||c.enumerable});return e})(t({},"__esModule",{value:!0}),e));var r=require("@walkeros/core"),c=require("@walkeros/server-core");var a=async function(e,{config:t,rule:n,data:i,env:o,logger:s,collector:a}){const l=t.settings,{apiKey:m,apiSecret:g,pod:v="us1",environment:d="production",userIdentities:f,userAttributes:y,consent:b,ip:_,sourceRequestId:O}=l,j=n?.settings||{},w=(0,r.isObject)(i)?i:{},h=await async function(e,t,n,i){const o={...(0,r.isObject)(t)?t:{},...(0,r.isObject)(n)?n:{}},s=Object.keys(o);if(0===s.length)return;const c={};for(const t of s){const n=p(await(0,r.getMappingValue)(e,o[t],{collector:i}));void 0!==n&&(c[t]=n)}return Object.keys(c).length>0?c:void 0}(e,f,j.userIdentities,a),k=await async function(e,t,n,i){const o=t?await(0,r.getMappingValue)(e,t,{collector:i}):void 0,s=n?await(0,r.getMappingValue)(e,n,{collector:i}):void 0,c={...(0,r.isObject)(o)?o:{},...(0,r.isObject)(s)?s:{}};return Object.keys(c).length>0?c:void 0}(e,y,j.userAttributes,a),P=_?u(await(0,r.getMappingValue)(e,_,{collector:a})):void 0,S=u(O?await(0,r.getMappingValue)(e,O,{collector:a}):void 0)??(e.id||void 0),I=n?.name||e.name,M=e.timestamp||Date.now(),q=e.id||void 0,x=j.eventType||"custom_event";let A;if("screen_view"===x)A=function(e,t,n,i){return{event_type:"screen_view",data:{...e?{screen_name:e}:{},...t&&Object.keys(t).length>0?{custom_attributes:t}:{},...void 0!==n?{timestamp_unixtime_ms:n}:{},...i?{source_message_id:i}:{}}}}(I,w,M,q);else if("commerce_event"===x){const t=j.commerce?await(0,r.getMappingValue)(e,j.commerce,{collector:a}):void 0;A=function(e,t,n,i){return{event_type:"commerce_event",data:{...e||{},...t&&Object.keys(t).length>0?{custom_attributes:t}:{},...void 0!==n?{timestamp_unixtime_ms:n}:{},...i?{source_message_id:i}:{}}}}((0,r.isObject)(t)?t:void 0,w,M,q)}else{A=function(e,t,n,i,o){return{event_type:"custom_event",data:{event_name:e,custom_event_type:t,...n&&Object.keys(n).length>0?{custom_attributes:n}:{},...void 0!==i?{timestamp_unixtime_ms:i}:{},...o?{source_message_id:o}:{}}}}(I,j.customEventType||"other",w,M,q)}const V=function(e,t,n,i,o={}){const s={events:e,environment:i};return t&&Object.keys(t).length>0&&(s.user_identities=t),n&&Object.keys(n).length>0&&(s.user_attributes=n),o.ip&&(s.ip=o.ip),o.sourceRequestId&&(s.source_request_id=o.sourceRequestId),o.consent&&(s.consent_state=o.consent),o.context&&(s.context=o.context),s}([A],h,k,d,{ip:P,sourceRequestId:S,consent:b}),T=function(e="us1"){return"us1"===e?"https://s2s.mparticle.com/v2/events":`https://s2s.${e}.mparticle.com/v2/events`}(v),$=function(e,t){return`Basic ${Buffer.from(`${e}:${t}`).toString("base64")}`}(m,g);s.debug("Calling mParticle Events API",{endpoint:T,method:"POST",eventType:A.event_type,eventName:I,eventId:e.id});const C=o?.sendServer||c.sendServer,K=await C(T,JSON.stringify(V),{headers:{Authorization:$,"Content-Type":"application/json"}});s.debug("mParticle API response",{ok:!(0,r.isObject)(K)||K.ok}),(0,r.isObject)(K)&&!1===K.ok&&s.throw(`mParticle API error: ${JSON.stringify(K)}`)};function u(e){if(null!=e)return"string"==typeof e?e||void 0:"number"==typeof e||"boolean"==typeof e?String(e):void 0}function p(e){if(null!=e)return"string"==typeof e?e||void 0:"number"==typeof e?e:"boolean"==typeof e?String(e):void 0}var l={},m={type:"mparticle",config:{},async init({config:e,logger:t}){const n=function(e={},t){const n=e.settings||{},{apiKey:i,apiSecret:o}=n;i||t.throw("Config settings apiKey missing"),o||t.throw("Config settings apiSecret missing");const s={pod:"us1",environment:"production",...n,apiKey:i,apiSecret:o};return{...e,settings:s}}(e,t);return n},push:async(e,t)=>await a(e,t)},g=m;//# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/batch.ts","../src/types/index.ts"],"sourcesContent":["import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationMParticle from './types';\n\nexport const destinationMParticle: Destination = {\n type: 'mparticle',\n\n config: {},\n\n async init({ config: partialConfig, logger }) {\n const config = getConfig(partialConfig, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationMParticle;\n","import type { Config, PartialConfig, Settings } from './types';\nimport type { Logger } from '@walkeros/core';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { apiKey, apiSecret } = settings;\n\n if (!apiKey) logger.throw('Config settings apiKey missing');\n if (!apiSecret) logger.throw('Config settings apiSecret missing');\n\n const settingsConfig: Settings = {\n pod: 'us1',\n environment: 'production',\n ...settings,\n apiKey: apiKey as string,\n apiSecret: apiSecret as string,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { WalkerOS, Mapping as WalkerOSMapping } from '@walkeros/core';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { sendServer } from '@walkeros/server-core';\nimport type {\n CommerceEventData,\n ConsentState,\n CustomEventType,\n Mapping,\n MParticleEvent,\n PushFn,\n Settings,\n} from './types';\nimport {\n buildAuthHeader,\n buildBatch,\n buildCommerceEvent,\n buildCustomEvent,\n buildEndpoint,\n buildScreenViewEvent,\n} from './batch';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, env, logger },\n) {\n const settings = config.settings as Settings;\n const {\n apiKey,\n apiSecret,\n pod = 'us1',\n environment = 'production',\n userIdentities: settingsIdentities,\n userAttributes: settingsUserAttributes,\n consent,\n ip: ipSetting,\n sourceRequestId: sourceRequestIdSetting,\n } = settings;\n\n const ruleSettings: Mapping = (rule?.settings || {}) as Mapping;\n\n const customAttributes = isObject(data)\n ? (data as Record<string, unknown>)\n : {};\n\n const userIdentities = await resolveIdentities(\n event,\n settingsIdentities,\n ruleSettings.userIdentities,\n );\n\n const userAttributes = await resolveUserAttributes(\n event,\n settingsUserAttributes,\n ruleSettings.userAttributes,\n );\n\n const ip = ipSetting\n ? toStringValue(await getMappingValue(event, ipSetting))\n : undefined;\n\n const sourceRequestIdRaw = sourceRequestIdSetting\n ? await getMappingValue(event, sourceRequestIdSetting)\n : undefined;\n const sourceRequestId =\n toStringValue(sourceRequestIdRaw) ?? (event.id || undefined);\n\n const eventName = rule?.name || event.name;\n const timestamp = event.timestamp || Date.now();\n const sourceMessageId = event.id || undefined;\n const eventType = ruleSettings.eventType || 'custom_event';\n\n let mpEvent: MParticleEvent;\n if (eventType === 'screen_view') {\n mpEvent = buildScreenViewEvent(\n eventName,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n } else if (eventType === 'commerce_event') {\n const commerceResolved = ruleSettings.commerce\n ? await getMappingValue(event, ruleSettings.commerce)\n : undefined;\n const commerceData = isObject(commerceResolved)\n ? (commerceResolved as Partial<CommerceEventData>)\n : undefined;\n mpEvent = buildCommerceEvent(\n commerceData,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n } else {\n const customEventType: CustomEventType =\n ruleSettings.customEventType || 'other';\n mpEvent = buildCustomEvent(\n eventName,\n customEventType,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n }\n\n const batch = buildBatch(\n [mpEvent],\n userIdentities,\n userAttributes,\n environment,\n {\n ip,\n sourceRequestId,\n consent: consent as ConsentState | undefined,\n },\n );\n\n const endpoint = buildEndpoint(pod);\n const authHeader = buildAuthHeader(apiKey, apiSecret);\n\n logger.debug('Calling mParticle Events API', {\n endpoint,\n method: 'POST',\n eventType: mpEvent.event_type,\n eventName,\n eventId: event.id,\n });\n\n const sendServerFn = env?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(batch), {\n headers: {\n Authorization: authHeader,\n 'Content-Type': 'application/json',\n },\n });\n\n logger.debug('mParticle API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`mParticle API error: ${JSON.stringify(result)}`);\n }\n};\n\nasync function resolveIdentities(\n event: WalkerOS.Event,\n settingsIdentities: WalkerOSMapping.Map | undefined,\n ruleIdentities: WalkerOSMapping.Map | undefined,\n): Promise<Record<string, string | number> | undefined> {\n const merged: WalkerOSMapping.Map = {\n ...(isObject(settingsIdentities) ? settingsIdentities : {}),\n ...(isObject(ruleIdentities) ? ruleIdentities : {}),\n };\n const keys = Object.keys(merged);\n if (keys.length === 0) return undefined;\n\n const out: Record<string, string | number> = {};\n for (const key of keys) {\n const raw = await getMappingValue(event, merged[key]);\n const coerced = toIdentityValue(raw);\n if (coerced !== undefined) out[key] = coerced;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nasync function resolveUserAttributes(\n event: WalkerOS.Event,\n settingsAttributes: WalkerOSMapping.Value | undefined,\n ruleAttributes: WalkerOSMapping.Value | undefined,\n): Promise<Record<string, unknown> | undefined> {\n const settingsResolved = settingsAttributes\n ? await getMappingValue(event, settingsAttributes)\n : undefined;\n const ruleResolved = ruleAttributes\n ? await getMappingValue(event, ruleAttributes)\n : undefined;\n\n const merged: Record<string, unknown> = {\n ...(isObject(settingsResolved)\n ? (settingsResolved as Record<string, unknown>)\n : {}),\n ...(isObject(ruleResolved)\n ? (ruleResolved as Record<string, unknown>)\n : {}),\n };\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\nfunction toStringValue(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value || undefined;\n if (typeof value === 'number' || typeof value === 'boolean')\n return String(value);\n return undefined;\n}\n\nfunction toIdentityValue(value: unknown): string | number | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value || undefined;\n if (typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n return undefined;\n}\n","import type {\n CommerceEventData,\n ConsentState,\n CustomEventType,\n Environment,\n MParticleBatch,\n MParticleEvent,\n Pod,\n ScreenViewEventData,\n} from './types';\n\n/**\n * Returns the mParticle Events API endpoint for the given pod.\n * us1 resolves to the legacy host (`s2s.mparticle.com`); other pods use the\n * pod-qualified host.\n * https://docs.mparticle.com/developers/server/http/#endpoint\n */\nexport function buildEndpoint(pod: Pod = 'us1'): string {\n if (pod === 'us1') return 'https://s2s.mparticle.com/v2/events';\n return `https://s2s.${pod}.mparticle.com/v2/events`;\n}\n\n/**\n * Builds the HTTP Basic auth header value from an API key/secret pair.\n * Uses Buffer (Node) for base64 encoding to keep server semantics.\n */\nexport function buildAuthHeader(apiKey: string, apiSecret: string): string {\n const token = Buffer.from(`${apiKey}:${apiSecret}`).toString('base64');\n return `Basic ${token}`;\n}\n\n/**\n * Builds a custom_event payload.\n */\nexport function buildCustomEvent(\n eventName: string,\n customEventType: CustomEventType,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n return {\n event_type: 'custom_event',\n data: {\n event_name: eventName,\n custom_event_type: customEventType,\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n },\n };\n}\n\n/**\n * Builds a screen_view event payload.\n */\nexport function buildScreenViewEvent(\n screenName: string | undefined,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n const data: ScreenViewEventData = {\n ...(screenName ? { screen_name: screenName } : {}),\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n };\n return { event_type: 'screen_view', data };\n}\n\n/**\n * Builds a commerce_event payload. Commerce data is a loosely-shaped subset\n * of {@link CommerceEventData} (product_action, currency_code, ...) resolved\n * from the per-rule commerce mapping.\n */\nexport function buildCommerceEvent(\n commerceData: Partial<CommerceEventData> | undefined,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n const data: CommerceEventData = {\n ...(commerceData || {}),\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n };\n return { event_type: 'commerce_event', data };\n}\n\nexport interface BuildBatchOptions {\n ip?: string;\n sourceRequestId?: string;\n consent?: ConsentState;\n context?: Record<string, unknown>;\n}\n\n/**\n * Assembles the batch envelope wrapping events + identity + environment.\n */\nexport function buildBatch(\n events: MParticleEvent[],\n userIdentities: Record<string, string | number> | undefined,\n userAttributes: Record<string, unknown> | undefined,\n environment: Environment,\n options: BuildBatchOptions = {},\n): MParticleBatch {\n const batch: MParticleBatch = {\n events,\n environment,\n };\n if (userIdentities && Object.keys(userIdentities).length > 0)\n batch.user_identities = userIdentities;\n if (userAttributes && Object.keys(userAttributes).length > 0)\n batch.user_attributes = userAttributes;\n if (options.ip) batch.ip = options.ip;\n if (options.sourceRequestId)\n batch.source_request_id = options.sourceRequestId;\n if (options.consent) batch.consent_state = options.consent;\n if (options.context) batch.context = options.context;\n return batch;\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\n\n/**\n * mParticle data pod. Determines the regional endpoint used for the Events\n * API. Defaults to `us1`. See {@link buildEndpoint} in `batch.ts`.\n */\nexport type Pod = 'us1' | 'us2' | 'eu1' | 'au1';\n\n/**\n * mParticle environment for the batch. `production` routes to production\n * data streams; `development` sends to debug/verify streams.\n */\nexport type Environment = 'production' | 'development';\n\n/**\n * Event type used for the outgoing mParticle event. Defaults to\n * `custom_event` when not explicitly mapped via rule settings.\n */\nexport type EventType = 'custom_event' | 'screen_view' | 'commerce_event';\n\n/**\n * mParticle custom event type (category) for `custom_event`s. Defaults to\n * `other` when not specified.\n */\nexport type CustomEventType =\n | 'navigation'\n | 'location'\n | 'search'\n | 'transaction'\n | 'user_content'\n | 'user_preference'\n | 'social'\n | 'media'\n | 'attribution'\n | 'other';\n\n/**\n * mParticle product action verbs for commerce events.\n */\nexport type ProductActionType =\n | 'add_to_cart'\n | 'remove_from_cart'\n | 'checkout'\n | 'checkout_option'\n | 'click'\n | 'view_detail'\n | 'purchase'\n | 'refund'\n | 'add_to_wishlist'\n | 'remove_from_wishlist';\n\nexport interface Settings {\n /** mParticle input feed API key. */\n apiKey: string;\n /** mParticle input feed API secret. */\n apiSecret: string;\n /** Data pod selecting the regional endpoint. Default: `us1`. */\n pod?: Pod;\n /** Environment the batch targets. Default: `production`. */\n environment?: Environment;\n /**\n * Mapping that resolves to `user_identities` per batch. Each entry value\n * is a walkerOS mapping value; the resolved object is placed into the\n * mParticle batch `user_identities` envelope.\n */\n userIdentities?: WalkerOSMapping.Map;\n /**\n * Mapping that resolves to `user_attributes` per batch.\n */\n userAttributes?: WalkerOSMapping.Value;\n /**\n * Optional static consent state passthrough — shape is forwarded verbatim\n * to `consent_state` on the batch.\n */\n consent?: ConsentState;\n /** walkerOS mapping value resolving to the client IP for the batch. */\n ip?: WalkerOSMapping.Value;\n /**\n * Optional request correlation id. When omitted, falls back to `event.id`.\n */\n sourceRequestId?: WalkerOSMapping.Value;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Determines which mParticle event shape is\n * produced for this walkerOS event and allows per-event identity overrides.\n */\nexport interface Mapping {\n /** Event type. Default: `custom_event`. */\n eventType?: EventType;\n /** Custom event type category for `custom_event`. Default: `other`. */\n customEventType?: CustomEventType;\n /** Commerce mapping resolving to ProductAction and related fields. */\n commerce?: WalkerOSMapping.Value;\n /** Per-event override for `user_identities`. Merged over settings. */\n userIdentities?: WalkerOSMapping.Map;\n /** Per-event override for `user_attributes`. */\n userAttributes?: WalkerOSMapping.Value;\n}\n\nexport interface Env extends DestinationServer.Env {\n sendServer?: typeof sendServer;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination 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>;\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n/**\n * Top-level mParticle batch payload posted to\n * `https://s2s.{pod}.mparticle.com/v2/events`.\n * https://docs.mparticle.com/developers/server/http/\n */\nexport interface MParticleBatch {\n events: MParticleEvent[];\n user_identities?: Record<string, string | number>;\n user_attributes?: Record<string, unknown>;\n environment: Environment;\n schema_version?: number;\n ip?: string;\n source_request_id?: string;\n consent_state?: ConsentState;\n context?: Record<string, unknown>;\n}\n\nexport type MParticleEvent =\n | { event_type: 'custom_event'; data: CustomEventData }\n | { event_type: 'screen_view'; data: ScreenViewEventData }\n | { event_type: 'commerce_event'; data: CommerceEventData };\n\nexport interface CommonEventData {\n timestamp_unixtime_ms?: number;\n source_message_id?: string;\n session_uuid?: string;\n custom_attributes?: Record<string, unknown>;\n custom_flags?: Record<string, unknown>;\n location?: Record<string, unknown>;\n}\n\nexport interface CustomEventData extends CommonEventData {\n event_name: string;\n custom_event_type: CustomEventType;\n}\n\nexport interface ScreenViewEventData extends CommonEventData {\n screen_name?: string;\n}\n\nexport interface CommerceEventData extends CommonEventData {\n product_action?: ProductAction;\n promotion_action?: PromotionAction;\n product_impressions?: ProductImpression[];\n currency_code?: string;\n is_non_interactive?: boolean;\n}\n\nexport interface ProductAction {\n action: ProductActionType;\n transaction_id?: string;\n total_amount?: number;\n tax_amount?: number;\n shipping_amount?: number;\n coupon_code?: string;\n affiliation?: string;\n checkout_step?: number;\n checkout_options?: string;\n products?: Product[];\n}\n\nexport interface Product {\n id?: string;\n name?: string;\n brand?: string;\n category?: string;\n variant?: string;\n position?: number;\n price?: number;\n quantity?: number;\n coupon_code?: string;\n total_product_amount?: number;\n custom_attributes?: Record<string, unknown>;\n}\n\nexport interface PromotionAction {\n action: 'view' | 'click';\n promotions?: Array<{\n id?: string;\n name?: string;\n creative?: string;\n position?: string;\n }>;\n}\n\nexport interface ProductImpression {\n product_impression_list?: string;\n products?: Product[];\n}\n\n/**\n * mParticle consent state envelope forwarded verbatim on the batch.\n * https://docs.mparticle.com/developers/server/http/#consent-state\n */\nexport interface ConsentState {\n gdpr?: Record<string, GDPRConsentState>;\n ccpa?: { data_sale_opt_out?: CCPAConsentState };\n}\n\nexport interface GDPRConsentState {\n consented: boolean;\n document?: string;\n timestamp_unixtime_ms?: number;\n location?: string;\n hardware_id?: string;\n}\n\nexport interface CCPAConsentState {\n consented: boolean;\n document?: string;\n timestamp_unixtime_ms?: number;\n location?: string;\n hardware_id?: string;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/batch.ts","../src/types/index.ts"],"sourcesContent":["import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationMParticle from './types';\n\nexport const destinationMParticle: Destination = {\n type: 'mparticle',\n\n config: {},\n\n async init({ config: partialConfig, logger }) {\n const config = getConfig(partialConfig, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationMParticle;\n","import type { Config, PartialConfig, Settings } from './types';\nimport type { Logger } from '@walkeros/core';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { apiKey, apiSecret } = settings;\n\n if (!apiKey) logger.throw('Config settings apiKey missing');\n if (!apiSecret) logger.throw('Config settings apiSecret missing');\n\n const settingsConfig: Settings = {\n pod: 'us1',\n environment: 'production',\n ...settings,\n apiKey: apiKey as string,\n apiSecret: apiSecret as string,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n Collector,\n WalkerOS,\n Mapping as WalkerOSMapping,\n} from '@walkeros/core';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { sendServer } from '@walkeros/server-core';\nimport type {\n CommerceEventData,\n ConsentState,\n CustomEventType,\n Mapping,\n MParticleEvent,\n PushFn,\n Settings,\n} from './types';\nimport {\n buildAuthHeader,\n buildBatch,\n buildCommerceEvent,\n buildCustomEvent,\n buildEndpoint,\n buildScreenViewEvent,\n} from './batch';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, env, logger, collector },\n) {\n const settings = config.settings as Settings;\n const {\n apiKey,\n apiSecret,\n pod = 'us1',\n environment = 'production',\n userIdentities: settingsIdentities,\n userAttributes: settingsUserAttributes,\n consent,\n ip: ipSetting,\n sourceRequestId: sourceRequestIdSetting,\n } = settings;\n\n const ruleSettings: Mapping = (rule?.settings || {}) as Mapping;\n\n const customAttributes = isObject(data)\n ? (data as Record<string, unknown>)\n : {};\n\n const userIdentities = await resolveIdentities(\n event,\n settingsIdentities,\n ruleSettings.userIdentities,\n collector,\n );\n\n const userAttributes = await resolveUserAttributes(\n event,\n settingsUserAttributes,\n ruleSettings.userAttributes,\n collector,\n );\n\n const ip = ipSetting\n ? toStringValue(await getMappingValue(event, ipSetting, { collector }))\n : undefined;\n\n const sourceRequestIdRaw = sourceRequestIdSetting\n ? await getMappingValue(event, sourceRequestIdSetting, { collector })\n : undefined;\n const sourceRequestId =\n toStringValue(sourceRequestIdRaw) ?? (event.id || undefined);\n\n const eventName = rule?.name || event.name;\n const timestamp = event.timestamp || Date.now();\n const sourceMessageId = event.id || undefined;\n const eventType = ruleSettings.eventType || 'custom_event';\n\n let mpEvent: MParticleEvent;\n if (eventType === 'screen_view') {\n mpEvent = buildScreenViewEvent(\n eventName,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n } else if (eventType === 'commerce_event') {\n const commerceResolved = ruleSettings.commerce\n ? await getMappingValue(event, ruleSettings.commerce, { collector })\n : undefined;\n const commerceData = isObject(commerceResolved)\n ? (commerceResolved as Partial<CommerceEventData>)\n : undefined;\n mpEvent = buildCommerceEvent(\n commerceData,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n } else {\n const customEventType: CustomEventType =\n ruleSettings.customEventType || 'other';\n mpEvent = buildCustomEvent(\n eventName,\n customEventType,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n }\n\n const batch = buildBatch(\n [mpEvent],\n userIdentities,\n userAttributes,\n environment,\n {\n ip,\n sourceRequestId,\n consent: consent as ConsentState | undefined,\n },\n );\n\n const endpoint = buildEndpoint(pod);\n const authHeader = buildAuthHeader(apiKey, apiSecret);\n\n logger.debug('Calling mParticle Events API', {\n endpoint,\n method: 'POST',\n eventType: mpEvent.event_type,\n eventName,\n eventId: event.id,\n });\n\n const sendServerFn = env?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(batch), {\n headers: {\n Authorization: authHeader,\n 'Content-Type': 'application/json',\n },\n });\n\n logger.debug('mParticle API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`mParticle API error: ${JSON.stringify(result)}`);\n }\n};\n\nasync function resolveIdentities(\n event: WalkerOS.Event,\n settingsIdentities: WalkerOSMapping.Map | undefined,\n ruleIdentities: WalkerOSMapping.Map | undefined,\n collector: Collector.Instance,\n): Promise<Record<string, string | number> | undefined> {\n const merged: WalkerOSMapping.Map = {\n ...(isObject(settingsIdentities) ? settingsIdentities : {}),\n ...(isObject(ruleIdentities) ? ruleIdentities : {}),\n };\n const keys = Object.keys(merged);\n if (keys.length === 0) return undefined;\n\n const out: Record<string, string | number> = {};\n for (const key of keys) {\n const raw = await getMappingValue(event, merged[key], { collector });\n const coerced = toIdentityValue(raw);\n if (coerced !== undefined) out[key] = coerced;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nasync function resolveUserAttributes(\n event: WalkerOS.Event,\n settingsAttributes: WalkerOSMapping.Value | undefined,\n ruleAttributes: WalkerOSMapping.Value | undefined,\n collector: Collector.Instance,\n): Promise<Record<string, unknown> | undefined> {\n const settingsResolved = settingsAttributes\n ? await getMappingValue(event, settingsAttributes, { collector })\n : undefined;\n const ruleResolved = ruleAttributes\n ? await getMappingValue(event, ruleAttributes, { collector })\n : undefined;\n\n const merged: Record<string, unknown> = {\n ...(isObject(settingsResolved)\n ? (settingsResolved as Record<string, unknown>)\n : {}),\n ...(isObject(ruleResolved)\n ? (ruleResolved as Record<string, unknown>)\n : {}),\n };\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\nfunction toStringValue(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value || undefined;\n if (typeof value === 'number' || typeof value === 'boolean')\n return String(value);\n return undefined;\n}\n\nfunction toIdentityValue(value: unknown): string | number | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value || undefined;\n if (typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n return undefined;\n}\n","import type {\n CommerceEventData,\n ConsentState,\n CustomEventType,\n Environment,\n MParticleBatch,\n MParticleEvent,\n Pod,\n ScreenViewEventData,\n} from './types';\n\n/**\n * Returns the mParticle Events API endpoint for the given pod.\n * us1 resolves to the legacy host (`s2s.mparticle.com`); other pods use the\n * pod-qualified host.\n * https://docs.mparticle.com/developers/server/http/#endpoint\n */\nexport function buildEndpoint(pod: Pod = 'us1'): string {\n if (pod === 'us1') return 'https://s2s.mparticle.com/v2/events';\n return `https://s2s.${pod}.mparticle.com/v2/events`;\n}\n\n/**\n * Builds the HTTP Basic auth header value from an API key/secret pair.\n * Uses Buffer (Node) for base64 encoding to keep server semantics.\n */\nexport function buildAuthHeader(apiKey: string, apiSecret: string): string {\n const token = Buffer.from(`${apiKey}:${apiSecret}`).toString('base64');\n return `Basic ${token}`;\n}\n\n/**\n * Builds a custom_event payload.\n */\nexport function buildCustomEvent(\n eventName: string,\n customEventType: CustomEventType,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n return {\n event_type: 'custom_event',\n data: {\n event_name: eventName,\n custom_event_type: customEventType,\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n },\n };\n}\n\n/**\n * Builds a screen_view event payload.\n */\nexport function buildScreenViewEvent(\n screenName: string | undefined,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n const data: ScreenViewEventData = {\n ...(screenName ? { screen_name: screenName } : {}),\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n };\n return { event_type: 'screen_view', data };\n}\n\n/**\n * Builds a commerce_event payload. Commerce data is a loosely-shaped subset\n * of {@link CommerceEventData} (product_action, currency_code, ...) resolved\n * from the per-rule commerce mapping.\n */\nexport function buildCommerceEvent(\n commerceData: Partial<CommerceEventData> | undefined,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n const data: CommerceEventData = {\n ...(commerceData || {}),\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n };\n return { event_type: 'commerce_event', data };\n}\n\nexport interface BuildBatchOptions {\n ip?: string;\n sourceRequestId?: string;\n consent?: ConsentState;\n context?: Record<string, unknown>;\n}\n\n/**\n * Assembles the batch envelope wrapping events + identity + environment.\n */\nexport function buildBatch(\n events: MParticleEvent[],\n userIdentities: Record<string, string | number> | undefined,\n userAttributes: Record<string, unknown> | undefined,\n environment: Environment,\n options: BuildBatchOptions = {},\n): MParticleBatch {\n const batch: MParticleBatch = {\n events,\n environment,\n };\n if (userIdentities && Object.keys(userIdentities).length > 0)\n batch.user_identities = userIdentities;\n if (userAttributes && Object.keys(userAttributes).length > 0)\n batch.user_attributes = userAttributes;\n if (options.ip) batch.ip = options.ip;\n if (options.sourceRequestId)\n batch.source_request_id = options.sourceRequestId;\n if (options.consent) batch.consent_state = options.consent;\n if (options.context) batch.context = options.context;\n return batch;\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\n\n/**\n * mParticle data pod. Determines the regional endpoint used for the Events\n * API. Defaults to `us1`. See {@link buildEndpoint} in `batch.ts`.\n */\nexport type Pod = 'us1' | 'us2' | 'eu1' | 'au1';\n\n/**\n * mParticle environment for the batch. `production` routes to production\n * data streams; `development` sends to debug/verify streams.\n */\nexport type Environment = 'production' | 'development';\n\n/**\n * Event type used for the outgoing mParticle event. Defaults to\n * `custom_event` when not explicitly mapped via rule settings.\n */\nexport type EventType = 'custom_event' | 'screen_view' | 'commerce_event';\n\n/**\n * mParticle custom event type (category) for `custom_event`s. Defaults to\n * `other` when not specified.\n */\nexport type CustomEventType =\n | 'navigation'\n | 'location'\n | 'search'\n | 'transaction'\n | 'user_content'\n | 'user_preference'\n | 'social'\n | 'media'\n | 'attribution'\n | 'other';\n\n/**\n * mParticle product action verbs for commerce events.\n */\nexport type ProductActionType =\n | 'add_to_cart'\n | 'remove_from_cart'\n | 'checkout'\n | 'checkout_option'\n | 'click'\n | 'view_detail'\n | 'purchase'\n | 'refund'\n | 'add_to_wishlist'\n | 'remove_from_wishlist';\n\nexport interface Settings {\n /** mParticle input feed API key. */\n apiKey: string;\n /** mParticle input feed API secret. */\n apiSecret: string;\n /** Data pod selecting the regional endpoint. Default: `us1`. */\n pod?: Pod;\n /** Environment the batch targets. Default: `production`. */\n environment?: Environment;\n /**\n * Mapping that resolves to `user_identities` per batch. Each entry value\n * is a walkerOS mapping value; the resolved object is placed into the\n * mParticle batch `user_identities` envelope.\n */\n userIdentities?: WalkerOSMapping.Map;\n /**\n * Mapping that resolves to `user_attributes` per batch.\n */\n userAttributes?: WalkerOSMapping.Value;\n /**\n * Optional static consent state passthrough — shape is forwarded verbatim\n * to `consent_state` on the batch.\n */\n consent?: ConsentState;\n /** walkerOS mapping value resolving to the client IP for the batch. */\n ip?: WalkerOSMapping.Value;\n /**\n * Optional request correlation id. When omitted, falls back to `event.id`.\n */\n sourceRequestId?: WalkerOSMapping.Value;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Determines which mParticle event shape is\n * produced for this walkerOS event and allows per-event identity overrides.\n */\nexport interface Mapping {\n /** Event type. Default: `custom_event`. */\n eventType?: EventType;\n /** Custom event type category for `custom_event`. Default: `other`. */\n customEventType?: CustomEventType;\n /** Commerce mapping resolving to ProductAction and related fields. */\n commerce?: WalkerOSMapping.Value;\n /** Per-event override for `user_identities`. Merged over settings. */\n userIdentities?: WalkerOSMapping.Map;\n /** Per-event override for `user_attributes`. */\n userAttributes?: WalkerOSMapping.Value;\n}\n\nexport interface Env extends DestinationServer.Env {\n sendServer?: typeof sendServer;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination 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>;\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n/**\n * Top-level mParticle batch payload posted to\n * `https://s2s.{pod}.mparticle.com/v2/events`.\n * https://docs.mparticle.com/developers/server/http/\n */\nexport interface MParticleBatch {\n events: MParticleEvent[];\n user_identities?: Record<string, string | number>;\n user_attributes?: Record<string, unknown>;\n environment: Environment;\n schema_version?: number;\n ip?: string;\n source_request_id?: string;\n consent_state?: ConsentState;\n context?: Record<string, unknown>;\n}\n\nexport type MParticleEvent =\n | { event_type: 'custom_event'; data: CustomEventData }\n | { event_type: 'screen_view'; data: ScreenViewEventData }\n | { event_type: 'commerce_event'; data: CommerceEventData };\n\nexport interface CommonEventData {\n timestamp_unixtime_ms?: number;\n source_message_id?: string;\n session_uuid?: string;\n custom_attributes?: Record<string, unknown>;\n custom_flags?: Record<string, unknown>;\n location?: Record<string, unknown>;\n}\n\nexport interface CustomEventData extends CommonEventData {\n event_name: string;\n custom_event_type: CustomEventType;\n}\n\nexport interface ScreenViewEventData extends CommonEventData {\n screen_name?: string;\n}\n\nexport interface CommerceEventData extends CommonEventData {\n product_action?: ProductAction;\n promotion_action?: PromotionAction;\n product_impressions?: ProductImpression[];\n currency_code?: string;\n is_non_interactive?: boolean;\n}\n\nexport interface ProductAction {\n action: ProductActionType;\n transaction_id?: string;\n total_amount?: number;\n tax_amount?: number;\n shipping_amount?: number;\n coupon_code?: string;\n affiliation?: string;\n checkout_step?: number;\n checkout_options?: string;\n products?: Product[];\n}\n\nexport interface Product {\n id?: string;\n name?: string;\n brand?: string;\n category?: string;\n variant?: string;\n position?: number;\n price?: number;\n quantity?: number;\n coupon_code?: string;\n total_product_amount?: number;\n custom_attributes?: Record<string, unknown>;\n}\n\nexport interface PromotionAction {\n action: 'view' | 'click';\n promotions?: Array<{\n id?: string;\n name?: string;\n creative?: string;\n position?: string;\n }>;\n}\n\nexport interface ProductImpression {\n product_impression_list?: string;\n products?: Product[];\n}\n\n/**\n * mParticle consent state envelope forwarded verbatim on the batch.\n * https://docs.mparticle.com/developers/server/http/#consent-state\n */\nexport interface ConsentState {\n gdpr?: Record<string, GDPRConsentState>;\n ccpa?: { data_sale_opt_out?: CCPAConsentState };\n}\n\nexport interface GDPRConsentState {\n consented: boolean;\n document?: string;\n timestamp_unixtime_ms?: number;\n location?: string;\n hardware_id?: string;\n}\n\nexport interface CCPAConsentState {\n consented: boolean;\n document?: string;\n timestamp_unixtime_ms?: number;\n location?: string;\n hardware_id?: string;\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{getMappingValue as e,isObject as t}from"@walkeros/core";import{sendServer as n}from"@walkeros/server-core";var i=async function(i,{config:r,rule:c,data:a,env:u,logger:m}){const p=r.settings,{apiKey:v,apiSecret:d,pod:f="us1",environment:g="production",userIdentities:y,userAttributes:_,consent:l,ip:b,sourceRequestId:h}=p,w=c?.settings||{},k=t(a)?a:{},O=await async function(n,i,s){const r={...t(i)?i:{},...t(s)?s:{}},c=Object.keys(r);if(0===c.length)return;const a={};for(const t of c){const i=o(await e(n,r[t]));void 0!==i&&(a[t]=i)}return Object.keys(a).length>0?a:void 0}(i,y,w.userIdentities),S=await async function(n,i,s){const o=i?await e(n,i):void 0,r=s?await e(n,s):void 0,c={...t(o)?o:{},...t(r)?r:{}};return Object.keys(c).length>0?c:void 0}(i,_,w.userAttributes),I=b?s(await e(i,b)):void 0,j=s(h?await e(i,h):void 0)??(i.id||void 0),P=c?.name||i.name,x=i.timestamp||Date.now(),A=i.id||void 0,q=w.eventType||"custom_event";let T;if("screen_view"===q)T=function(e,t,n,i){return{event_type:"screen_view",data:{...e?{screen_name:e}:{},...t&&Object.keys(t).length>0?{custom_attributes:t}:{},...void 0!==n?{timestamp_unixtime_ms:n}:{},...i?{source_message_id:i}:{}}}}(P,k,x,A);else if("commerce_event"===q){const n=w.commerce?await e(i,w.commerce):void 0;T=function(e,t,n,i){return{event_type:"commerce_event",data:{...e||{},...t&&Object.keys(t).length>0?{custom_attributes:t}:{},...void 0!==n?{timestamp_unixtime_ms:n}:{},...i?{source_message_id:i}:{}}}}(t(n)?n:void 0,k,x,A)}else{T=function(e,t,n,i,s){return{event_type:"custom_event",data:{event_name:e,custom_event_type:t,...n&&Object.keys(n).length>0?{custom_attributes:n}:{},...void 0!==i?{timestamp_unixtime_ms:i}:{},...s?{source_message_id:s}:{}}}}(P,w.customEventType||"other",k,x,A)}const $=function(e,t,n,i,s={}){const o={events:e,environment:i};return t&&Object.keys(t).length>0&&(o.user_identities=t),n&&Object.keys(n).length>0&&(o.user_attributes=n),s.ip&&(o.ip=s.ip),s.sourceRequestId&&(o.source_request_id=s.sourceRequestId),s.consent&&(o.consent_state=s.consent),s.context&&(o.context=s.context),o}([T],O,S,g,{ip:I,sourceRequestId:j,consent:l}),C=function(e="us1"){return"us1"===e?"https://s2s.mparticle.com/v2/events":`https://s2s.${e}.mparticle.com/v2/events`}(f),K=function(e,t){return`Basic ${Buffer.from(`${e}:${t}`).toString("base64")}`}(v,d);m.debug("Calling mParticle Events API",{endpoint:C,method:"POST",eventType:T.event_type,eventName:P,eventId:i.id});const R=u?.sendServer||n,N=await R(C,JSON.stringify($),{headers:{Authorization:K,"Content-Type":"application/json"}});m.debug("mParticle API response",{ok:!t(N)||N.ok}),t(N)&&!1===N.ok&&m.throw(`mParticle API error: ${JSON.stringify(N)}`)};function s(e){if(null!=e)return"string"==typeof e?e||void 0:"number"==typeof e||"boolean"==typeof e?String(e):void 0}function o(e){if(null!=e)return"string"==typeof e?e||void 0:"number"==typeof e?e:"boolean"==typeof e?String(e):void 0}var r={},c={type:"mparticle",config:{},async init({config:e,logger:t}){const n=function(e={},t){const n=e.settings||{},{apiKey:i,apiSecret:s}=n;i||t.throw("Config settings apiKey missing"),s||t.throw("Config settings apiSecret missing");const o={pod:"us1",environment:"production",...n,apiKey:i,apiSecret:s};return{...e,settings:o}}(e,t);return n},push:async(e,t)=>await i(e,t)},a=c;export{r as DestinationMParticle,a as default,c as destinationMParticle};//# sourceMappingURL=index.mjs.map
1
+ import{getMappingValue as e,isObject as t}from"@walkeros/core";import{sendServer as n}from"@walkeros/server-core";var o=async function(o,{config:r,rule:c,data:a,env:u,logger:m,collector:p}){const v=r.settings,{apiKey:d,apiSecret:l,pod:f="us1",environment:g="production",userIdentities:y,userAttributes:_,consent:b,ip:h,sourceRequestId:w}=v,k=c?.settings||{},O=t(a)?a:{},S=await async function(n,o,i,r){const c={...t(o)?o:{},...t(i)?i:{}},a=Object.keys(c);if(0===a.length)return;const u={};for(const t of a){const o=s(await e(n,c[t],{collector:r}));void 0!==o&&(u[t]=o)}return Object.keys(u).length>0?u:void 0}(o,y,k.userIdentities,p),I=await async function(n,o,i,s){const r=o?await e(n,o,{collector:s}):void 0,c=i?await e(n,i,{collector:s}):void 0,a={...t(r)?r:{},...t(c)?c:{}};return Object.keys(a).length>0?a:void 0}(o,_,k.userAttributes,p),j=h?i(await e(o,h,{collector:p})):void 0,P=i(w?await e(o,w,{collector:p}):void 0)??(o.id||void 0),x=c?.name||o.name,A=o.timestamp||Date.now(),q=o.id||void 0,T=k.eventType||"custom_event";let $;if("screen_view"===T)$=function(e,t,n,o){return{event_type:"screen_view",data:{...e?{screen_name:e}:{},...t&&Object.keys(t).length>0?{custom_attributes:t}:{},...void 0!==n?{timestamp_unixtime_ms:n}:{},...o?{source_message_id:o}:{}}}}(x,O,A,q);else if("commerce_event"===T){const n=k.commerce?await e(o,k.commerce,{collector:p}):void 0;$=function(e,t,n,o){return{event_type:"commerce_event",data:{...e||{},...t&&Object.keys(t).length>0?{custom_attributes:t}:{},...void 0!==n?{timestamp_unixtime_ms:n}:{},...o?{source_message_id:o}:{}}}}(t(n)?n:void 0,O,A,q)}else{$=function(e,t,n,o,i){return{event_type:"custom_event",data:{event_name:e,custom_event_type:t,...n&&Object.keys(n).length>0?{custom_attributes:n}:{},...void 0!==o?{timestamp_unixtime_ms:o}:{},...i?{source_message_id:i}:{}}}}(x,k.customEventType||"other",O,A,q)}const C=function(e,t,n,o,i={}){const s={events:e,environment:o};return t&&Object.keys(t).length>0&&(s.user_identities=t),n&&Object.keys(n).length>0&&(s.user_attributes=n),i.ip&&(s.ip=i.ip),i.sourceRequestId&&(s.source_request_id=i.sourceRequestId),i.consent&&(s.consent_state=i.consent),i.context&&(s.context=i.context),s}([$],S,I,g,{ip:j,sourceRequestId:P,consent:b}),K=function(e="us1"){return"us1"===e?"https://s2s.mparticle.com/v2/events":`https://s2s.${e}.mparticle.com/v2/events`}(f),R=function(e,t){return`Basic ${Buffer.from(`${e}:${t}`).toString("base64")}`}(d,l);m.debug("Calling mParticle Events API",{endpoint:K,method:"POST",eventType:$.event_type,eventName:x,eventId:o.id});const N=u?.sendServer||n,B=await N(K,JSON.stringify(C),{headers:{Authorization:R,"Content-Type":"application/json"}});m.debug("mParticle API response",{ok:!t(B)||B.ok}),t(B)&&!1===B.ok&&m.throw(`mParticle API error: ${JSON.stringify(B)}`)};function i(e){if(null!=e)return"string"==typeof e?e||void 0:"number"==typeof e||"boolean"==typeof e?String(e):void 0}function s(e){if(null!=e)return"string"==typeof e?e||void 0:"number"==typeof e?e:"boolean"==typeof e?String(e):void 0}var r={},c={type:"mparticle",config:{},async init({config:e,logger:t}){const n=function(e={},t){const n=e.settings||{},{apiKey:o,apiSecret:i}=n;o||t.throw("Config settings apiKey missing"),i||t.throw("Config settings apiSecret missing");const s={pod:"us1",environment:"production",...n,apiKey:o,apiSecret:i};return{...e,settings:s}}(e,t);return n},push:async(e,t)=>await o(e,t)},a=c;export{r as DestinationMParticle,a as default,c as destinationMParticle};//# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/push.ts","../src/batch.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, PartialConfig, Settings } from './types';\nimport type { Logger } from '@walkeros/core';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { apiKey, apiSecret } = settings;\n\n if (!apiKey) logger.throw('Config settings apiKey missing');\n if (!apiSecret) logger.throw('Config settings apiSecret missing');\n\n const settingsConfig: Settings = {\n pod: 'us1',\n environment: 'production',\n ...settings,\n apiKey: apiKey as string,\n apiSecret: apiSecret as string,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { WalkerOS, Mapping as WalkerOSMapping } from '@walkeros/core';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { sendServer } from '@walkeros/server-core';\nimport type {\n CommerceEventData,\n ConsentState,\n CustomEventType,\n Mapping,\n MParticleEvent,\n PushFn,\n Settings,\n} from './types';\nimport {\n buildAuthHeader,\n buildBatch,\n buildCommerceEvent,\n buildCustomEvent,\n buildEndpoint,\n buildScreenViewEvent,\n} from './batch';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, env, logger },\n) {\n const settings = config.settings as Settings;\n const {\n apiKey,\n apiSecret,\n pod = 'us1',\n environment = 'production',\n userIdentities: settingsIdentities,\n userAttributes: settingsUserAttributes,\n consent,\n ip: ipSetting,\n sourceRequestId: sourceRequestIdSetting,\n } = settings;\n\n const ruleSettings: Mapping = (rule?.settings || {}) as Mapping;\n\n const customAttributes = isObject(data)\n ? (data as Record<string, unknown>)\n : {};\n\n const userIdentities = await resolveIdentities(\n event,\n settingsIdentities,\n ruleSettings.userIdentities,\n );\n\n const userAttributes = await resolveUserAttributes(\n event,\n settingsUserAttributes,\n ruleSettings.userAttributes,\n );\n\n const ip = ipSetting\n ? toStringValue(await getMappingValue(event, ipSetting))\n : undefined;\n\n const sourceRequestIdRaw = sourceRequestIdSetting\n ? await getMappingValue(event, sourceRequestIdSetting)\n : undefined;\n const sourceRequestId =\n toStringValue(sourceRequestIdRaw) ?? (event.id || undefined);\n\n const eventName = rule?.name || event.name;\n const timestamp = event.timestamp || Date.now();\n const sourceMessageId = event.id || undefined;\n const eventType = ruleSettings.eventType || 'custom_event';\n\n let mpEvent: MParticleEvent;\n if (eventType === 'screen_view') {\n mpEvent = buildScreenViewEvent(\n eventName,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n } else if (eventType === 'commerce_event') {\n const commerceResolved = ruleSettings.commerce\n ? await getMappingValue(event, ruleSettings.commerce)\n : undefined;\n const commerceData = isObject(commerceResolved)\n ? (commerceResolved as Partial<CommerceEventData>)\n : undefined;\n mpEvent = buildCommerceEvent(\n commerceData,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n } else {\n const customEventType: CustomEventType =\n ruleSettings.customEventType || 'other';\n mpEvent = buildCustomEvent(\n eventName,\n customEventType,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n }\n\n const batch = buildBatch(\n [mpEvent],\n userIdentities,\n userAttributes,\n environment,\n {\n ip,\n sourceRequestId,\n consent: consent as ConsentState | undefined,\n },\n );\n\n const endpoint = buildEndpoint(pod);\n const authHeader = buildAuthHeader(apiKey, apiSecret);\n\n logger.debug('Calling mParticle Events API', {\n endpoint,\n method: 'POST',\n eventType: mpEvent.event_type,\n eventName,\n eventId: event.id,\n });\n\n const sendServerFn = env?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(batch), {\n headers: {\n Authorization: authHeader,\n 'Content-Type': 'application/json',\n },\n });\n\n logger.debug('mParticle API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`mParticle API error: ${JSON.stringify(result)}`);\n }\n};\n\nasync function resolveIdentities(\n event: WalkerOS.Event,\n settingsIdentities: WalkerOSMapping.Map | undefined,\n ruleIdentities: WalkerOSMapping.Map | undefined,\n): Promise<Record<string, string | number> | undefined> {\n const merged: WalkerOSMapping.Map = {\n ...(isObject(settingsIdentities) ? settingsIdentities : {}),\n ...(isObject(ruleIdentities) ? ruleIdentities : {}),\n };\n const keys = Object.keys(merged);\n if (keys.length === 0) return undefined;\n\n const out: Record<string, string | number> = {};\n for (const key of keys) {\n const raw = await getMappingValue(event, merged[key]);\n const coerced = toIdentityValue(raw);\n if (coerced !== undefined) out[key] = coerced;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nasync function resolveUserAttributes(\n event: WalkerOS.Event,\n settingsAttributes: WalkerOSMapping.Value | undefined,\n ruleAttributes: WalkerOSMapping.Value | undefined,\n): Promise<Record<string, unknown> | undefined> {\n const settingsResolved = settingsAttributes\n ? await getMappingValue(event, settingsAttributes)\n : undefined;\n const ruleResolved = ruleAttributes\n ? await getMappingValue(event, ruleAttributes)\n : undefined;\n\n const merged: Record<string, unknown> = {\n ...(isObject(settingsResolved)\n ? (settingsResolved as Record<string, unknown>)\n : {}),\n ...(isObject(ruleResolved)\n ? (ruleResolved as Record<string, unknown>)\n : {}),\n };\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\nfunction toStringValue(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value || undefined;\n if (typeof value === 'number' || typeof value === 'boolean')\n return String(value);\n return undefined;\n}\n\nfunction toIdentityValue(value: unknown): string | number | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value || undefined;\n if (typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n return undefined;\n}\n","import type {\n CommerceEventData,\n ConsentState,\n CustomEventType,\n Environment,\n MParticleBatch,\n MParticleEvent,\n Pod,\n ScreenViewEventData,\n} from './types';\n\n/**\n * Returns the mParticle Events API endpoint for the given pod.\n * us1 resolves to the legacy host (`s2s.mparticle.com`); other pods use the\n * pod-qualified host.\n * https://docs.mparticle.com/developers/server/http/#endpoint\n */\nexport function buildEndpoint(pod: Pod = 'us1'): string {\n if (pod === 'us1') return 'https://s2s.mparticle.com/v2/events';\n return `https://s2s.${pod}.mparticle.com/v2/events`;\n}\n\n/**\n * Builds the HTTP Basic auth header value from an API key/secret pair.\n * Uses Buffer (Node) for base64 encoding to keep server semantics.\n */\nexport function buildAuthHeader(apiKey: string, apiSecret: string): string {\n const token = Buffer.from(`${apiKey}:${apiSecret}`).toString('base64');\n return `Basic ${token}`;\n}\n\n/**\n * Builds a custom_event payload.\n */\nexport function buildCustomEvent(\n eventName: string,\n customEventType: CustomEventType,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n return {\n event_type: 'custom_event',\n data: {\n event_name: eventName,\n custom_event_type: customEventType,\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n },\n };\n}\n\n/**\n * Builds a screen_view event payload.\n */\nexport function buildScreenViewEvent(\n screenName: string | undefined,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n const data: ScreenViewEventData = {\n ...(screenName ? { screen_name: screenName } : {}),\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n };\n return { event_type: 'screen_view', data };\n}\n\n/**\n * Builds a commerce_event payload. Commerce data is a loosely-shaped subset\n * of {@link CommerceEventData} (product_action, currency_code, ...) resolved\n * from the per-rule commerce mapping.\n */\nexport function buildCommerceEvent(\n commerceData: Partial<CommerceEventData> | undefined,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n const data: CommerceEventData = {\n ...(commerceData || {}),\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n };\n return { event_type: 'commerce_event', data };\n}\n\nexport interface BuildBatchOptions {\n ip?: string;\n sourceRequestId?: string;\n consent?: ConsentState;\n context?: Record<string, unknown>;\n}\n\n/**\n * Assembles the batch envelope wrapping events + identity + environment.\n */\nexport function buildBatch(\n events: MParticleEvent[],\n userIdentities: Record<string, string | number> | undefined,\n userAttributes: Record<string, unknown> | undefined,\n environment: Environment,\n options: BuildBatchOptions = {},\n): MParticleBatch {\n const batch: MParticleBatch = {\n events,\n environment,\n };\n if (userIdentities && Object.keys(userIdentities).length > 0)\n batch.user_identities = userIdentities;\n if (userAttributes && Object.keys(userAttributes).length > 0)\n batch.user_attributes = userAttributes;\n if (options.ip) batch.ip = options.ip;\n if (options.sourceRequestId)\n batch.source_request_id = options.sourceRequestId;\n if (options.consent) batch.consent_state = options.consent;\n if (options.context) batch.context = options.context;\n return batch;\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\n\n/**\n * mParticle data pod. Determines the regional endpoint used for the Events\n * API. Defaults to `us1`. See {@link buildEndpoint} in `batch.ts`.\n */\nexport type Pod = 'us1' | 'us2' | 'eu1' | 'au1';\n\n/**\n * mParticle environment for the batch. `production` routes to production\n * data streams; `development` sends to debug/verify streams.\n */\nexport type Environment = 'production' | 'development';\n\n/**\n * Event type used for the outgoing mParticle event. Defaults to\n * `custom_event` when not explicitly mapped via rule settings.\n */\nexport type EventType = 'custom_event' | 'screen_view' | 'commerce_event';\n\n/**\n * mParticle custom event type (category) for `custom_event`s. Defaults to\n * `other` when not specified.\n */\nexport type CustomEventType =\n | 'navigation'\n | 'location'\n | 'search'\n | 'transaction'\n | 'user_content'\n | 'user_preference'\n | 'social'\n | 'media'\n | 'attribution'\n | 'other';\n\n/**\n * mParticle product action verbs for commerce events.\n */\nexport type ProductActionType =\n | 'add_to_cart'\n | 'remove_from_cart'\n | 'checkout'\n | 'checkout_option'\n | 'click'\n | 'view_detail'\n | 'purchase'\n | 'refund'\n | 'add_to_wishlist'\n | 'remove_from_wishlist';\n\nexport interface Settings {\n /** mParticle input feed API key. */\n apiKey: string;\n /** mParticle input feed API secret. */\n apiSecret: string;\n /** Data pod selecting the regional endpoint. Default: `us1`. */\n pod?: Pod;\n /** Environment the batch targets. Default: `production`. */\n environment?: Environment;\n /**\n * Mapping that resolves to `user_identities` per batch. Each entry value\n * is a walkerOS mapping value; the resolved object is placed into the\n * mParticle batch `user_identities` envelope.\n */\n userIdentities?: WalkerOSMapping.Map;\n /**\n * Mapping that resolves to `user_attributes` per batch.\n */\n userAttributes?: WalkerOSMapping.Value;\n /**\n * Optional static consent state passthrough — shape is forwarded verbatim\n * to `consent_state` on the batch.\n */\n consent?: ConsentState;\n /** walkerOS mapping value resolving to the client IP for the batch. */\n ip?: WalkerOSMapping.Value;\n /**\n * Optional request correlation id. When omitted, falls back to `event.id`.\n */\n sourceRequestId?: WalkerOSMapping.Value;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Determines which mParticle event shape is\n * produced for this walkerOS event and allows per-event identity overrides.\n */\nexport interface Mapping {\n /** Event type. Default: `custom_event`. */\n eventType?: EventType;\n /** Custom event type category for `custom_event`. Default: `other`. */\n customEventType?: CustomEventType;\n /** Commerce mapping resolving to ProductAction and related fields. */\n commerce?: WalkerOSMapping.Value;\n /** Per-event override for `user_identities`. Merged over settings. */\n userIdentities?: WalkerOSMapping.Map;\n /** Per-event override for `user_attributes`. */\n userAttributes?: WalkerOSMapping.Value;\n}\n\nexport interface Env extends DestinationServer.Env {\n sendServer?: typeof sendServer;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination 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>;\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n/**\n * Top-level mParticle batch payload posted to\n * `https://s2s.{pod}.mparticle.com/v2/events`.\n * https://docs.mparticle.com/developers/server/http/\n */\nexport interface MParticleBatch {\n events: MParticleEvent[];\n user_identities?: Record<string, string | number>;\n user_attributes?: Record<string, unknown>;\n environment: Environment;\n schema_version?: number;\n ip?: string;\n source_request_id?: string;\n consent_state?: ConsentState;\n context?: Record<string, unknown>;\n}\n\nexport type MParticleEvent =\n | { event_type: 'custom_event'; data: CustomEventData }\n | { event_type: 'screen_view'; data: ScreenViewEventData }\n | { event_type: 'commerce_event'; data: CommerceEventData };\n\nexport interface CommonEventData {\n timestamp_unixtime_ms?: number;\n source_message_id?: string;\n session_uuid?: string;\n custom_attributes?: Record<string, unknown>;\n custom_flags?: Record<string, unknown>;\n location?: Record<string, unknown>;\n}\n\nexport interface CustomEventData extends CommonEventData {\n event_name: string;\n custom_event_type: CustomEventType;\n}\n\nexport interface ScreenViewEventData extends CommonEventData {\n screen_name?: string;\n}\n\nexport interface CommerceEventData extends CommonEventData {\n product_action?: ProductAction;\n promotion_action?: PromotionAction;\n product_impressions?: ProductImpression[];\n currency_code?: string;\n is_non_interactive?: boolean;\n}\n\nexport interface ProductAction {\n action: ProductActionType;\n transaction_id?: string;\n total_amount?: number;\n tax_amount?: number;\n shipping_amount?: number;\n coupon_code?: string;\n affiliation?: string;\n checkout_step?: number;\n checkout_options?: string;\n products?: Product[];\n}\n\nexport interface Product {\n id?: string;\n name?: string;\n brand?: string;\n category?: string;\n variant?: string;\n position?: number;\n price?: number;\n quantity?: number;\n coupon_code?: string;\n total_product_amount?: number;\n custom_attributes?: Record<string, unknown>;\n}\n\nexport interface PromotionAction {\n action: 'view' | 'click';\n promotions?: Array<{\n id?: string;\n name?: string;\n creative?: string;\n position?: string;\n }>;\n}\n\nexport interface ProductImpression {\n product_impression_list?: string;\n products?: Product[];\n}\n\n/**\n * mParticle consent state envelope forwarded verbatim on the batch.\n * https://docs.mparticle.com/developers/server/http/#consent-state\n */\nexport interface ConsentState {\n gdpr?: Record<string, GDPRConsentState>;\n ccpa?: { data_sale_opt_out?: CCPAConsentState };\n}\n\nexport interface GDPRConsentState {\n consented: boolean;\n document?: string;\n timestamp_unixtime_ms?: number;\n location?: string;\n hardware_id?: string;\n}\n\nexport interface CCPAConsentState {\n consented: boolean;\n document?: string;\n timestamp_unixtime_ms?: number;\n location?: string;\n hardware_id?: string;\n}\n","import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationMParticle from './types';\n\nexport const destinationMParticle: Destination = {\n type: 'mparticle',\n\n config: {},\n\n async init({ config: partialConfig, logger }) {\n const config = getConfig(partialConfig, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationMParticle;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/config.ts","../src/push.ts","../src/batch.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, PartialConfig, Settings } from './types';\nimport type { Logger } from '@walkeros/core';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { apiKey, apiSecret } = settings;\n\n if (!apiKey) logger.throw('Config settings apiKey missing');\n if (!apiSecret) logger.throw('Config settings apiSecret missing');\n\n const settingsConfig: Settings = {\n pod: 'us1',\n environment: 'production',\n ...settings,\n apiKey: apiKey as string,\n apiSecret: apiSecret as string,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n Collector,\n WalkerOS,\n Mapping as WalkerOSMapping,\n} from '@walkeros/core';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { sendServer } from '@walkeros/server-core';\nimport type {\n CommerceEventData,\n ConsentState,\n CustomEventType,\n Mapping,\n MParticleEvent,\n PushFn,\n Settings,\n} from './types';\nimport {\n buildAuthHeader,\n buildBatch,\n buildCommerceEvent,\n buildCustomEvent,\n buildEndpoint,\n buildScreenViewEvent,\n} from './batch';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, env, logger, collector },\n) {\n const settings = config.settings as Settings;\n const {\n apiKey,\n apiSecret,\n pod = 'us1',\n environment = 'production',\n userIdentities: settingsIdentities,\n userAttributes: settingsUserAttributes,\n consent,\n ip: ipSetting,\n sourceRequestId: sourceRequestIdSetting,\n } = settings;\n\n const ruleSettings: Mapping = (rule?.settings || {}) as Mapping;\n\n const customAttributes = isObject(data)\n ? (data as Record<string, unknown>)\n : {};\n\n const userIdentities = await resolveIdentities(\n event,\n settingsIdentities,\n ruleSettings.userIdentities,\n collector,\n );\n\n const userAttributes = await resolveUserAttributes(\n event,\n settingsUserAttributes,\n ruleSettings.userAttributes,\n collector,\n );\n\n const ip = ipSetting\n ? toStringValue(await getMappingValue(event, ipSetting, { collector }))\n : undefined;\n\n const sourceRequestIdRaw = sourceRequestIdSetting\n ? await getMappingValue(event, sourceRequestIdSetting, { collector })\n : undefined;\n const sourceRequestId =\n toStringValue(sourceRequestIdRaw) ?? (event.id || undefined);\n\n const eventName = rule?.name || event.name;\n const timestamp = event.timestamp || Date.now();\n const sourceMessageId = event.id || undefined;\n const eventType = ruleSettings.eventType || 'custom_event';\n\n let mpEvent: MParticleEvent;\n if (eventType === 'screen_view') {\n mpEvent = buildScreenViewEvent(\n eventName,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n } else if (eventType === 'commerce_event') {\n const commerceResolved = ruleSettings.commerce\n ? await getMappingValue(event, ruleSettings.commerce, { collector })\n : undefined;\n const commerceData = isObject(commerceResolved)\n ? (commerceResolved as Partial<CommerceEventData>)\n : undefined;\n mpEvent = buildCommerceEvent(\n commerceData,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n } else {\n const customEventType: CustomEventType =\n ruleSettings.customEventType || 'other';\n mpEvent = buildCustomEvent(\n eventName,\n customEventType,\n customAttributes,\n timestamp,\n sourceMessageId,\n );\n }\n\n const batch = buildBatch(\n [mpEvent],\n userIdentities,\n userAttributes,\n environment,\n {\n ip,\n sourceRequestId,\n consent: consent as ConsentState | undefined,\n },\n );\n\n const endpoint = buildEndpoint(pod);\n const authHeader = buildAuthHeader(apiKey, apiSecret);\n\n logger.debug('Calling mParticle Events API', {\n endpoint,\n method: 'POST',\n eventType: mpEvent.event_type,\n eventName,\n eventId: event.id,\n });\n\n const sendServerFn = env?.sendServer || sendServer;\n const result = await sendServerFn(endpoint, JSON.stringify(batch), {\n headers: {\n Authorization: authHeader,\n 'Content-Type': 'application/json',\n },\n });\n\n logger.debug('mParticle API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`mParticle API error: ${JSON.stringify(result)}`);\n }\n};\n\nasync function resolveIdentities(\n event: WalkerOS.Event,\n settingsIdentities: WalkerOSMapping.Map | undefined,\n ruleIdentities: WalkerOSMapping.Map | undefined,\n collector: Collector.Instance,\n): Promise<Record<string, string | number> | undefined> {\n const merged: WalkerOSMapping.Map = {\n ...(isObject(settingsIdentities) ? settingsIdentities : {}),\n ...(isObject(ruleIdentities) ? ruleIdentities : {}),\n };\n const keys = Object.keys(merged);\n if (keys.length === 0) return undefined;\n\n const out: Record<string, string | number> = {};\n for (const key of keys) {\n const raw = await getMappingValue(event, merged[key], { collector });\n const coerced = toIdentityValue(raw);\n if (coerced !== undefined) out[key] = coerced;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nasync function resolveUserAttributes(\n event: WalkerOS.Event,\n settingsAttributes: WalkerOSMapping.Value | undefined,\n ruleAttributes: WalkerOSMapping.Value | undefined,\n collector: Collector.Instance,\n): Promise<Record<string, unknown> | undefined> {\n const settingsResolved = settingsAttributes\n ? await getMappingValue(event, settingsAttributes, { collector })\n : undefined;\n const ruleResolved = ruleAttributes\n ? await getMappingValue(event, ruleAttributes, { collector })\n : undefined;\n\n const merged: Record<string, unknown> = {\n ...(isObject(settingsResolved)\n ? (settingsResolved as Record<string, unknown>)\n : {}),\n ...(isObject(ruleResolved)\n ? (ruleResolved as Record<string, unknown>)\n : {}),\n };\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\nfunction toStringValue(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value || undefined;\n if (typeof value === 'number' || typeof value === 'boolean')\n return String(value);\n return undefined;\n}\n\nfunction toIdentityValue(value: unknown): string | number | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value || undefined;\n if (typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n return undefined;\n}\n","import type {\n CommerceEventData,\n ConsentState,\n CustomEventType,\n Environment,\n MParticleBatch,\n MParticleEvent,\n Pod,\n ScreenViewEventData,\n} from './types';\n\n/**\n * Returns the mParticle Events API endpoint for the given pod.\n * us1 resolves to the legacy host (`s2s.mparticle.com`); other pods use the\n * pod-qualified host.\n * https://docs.mparticle.com/developers/server/http/#endpoint\n */\nexport function buildEndpoint(pod: Pod = 'us1'): string {\n if (pod === 'us1') return 'https://s2s.mparticle.com/v2/events';\n return `https://s2s.${pod}.mparticle.com/v2/events`;\n}\n\n/**\n * Builds the HTTP Basic auth header value from an API key/secret pair.\n * Uses Buffer (Node) for base64 encoding to keep server semantics.\n */\nexport function buildAuthHeader(apiKey: string, apiSecret: string): string {\n const token = Buffer.from(`${apiKey}:${apiSecret}`).toString('base64');\n return `Basic ${token}`;\n}\n\n/**\n * Builds a custom_event payload.\n */\nexport function buildCustomEvent(\n eventName: string,\n customEventType: CustomEventType,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n return {\n event_type: 'custom_event',\n data: {\n event_name: eventName,\n custom_event_type: customEventType,\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n },\n };\n}\n\n/**\n * Builds a screen_view event payload.\n */\nexport function buildScreenViewEvent(\n screenName: string | undefined,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n const data: ScreenViewEventData = {\n ...(screenName ? { screen_name: screenName } : {}),\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n };\n return { event_type: 'screen_view', data };\n}\n\n/**\n * Builds a commerce_event payload. Commerce data is a loosely-shaped subset\n * of {@link CommerceEventData} (product_action, currency_code, ...) resolved\n * from the per-rule commerce mapping.\n */\nexport function buildCommerceEvent(\n commerceData: Partial<CommerceEventData> | undefined,\n customAttributes: Record<string, unknown> | undefined,\n timestamp: number | undefined,\n sourceMessageId: string | undefined,\n): MParticleEvent {\n const data: CommerceEventData = {\n ...(commerceData || {}),\n ...(customAttributes && Object.keys(customAttributes).length > 0\n ? { custom_attributes: customAttributes }\n : {}),\n ...(timestamp !== undefined ? { timestamp_unixtime_ms: timestamp } : {}),\n ...(sourceMessageId ? { source_message_id: sourceMessageId } : {}),\n };\n return { event_type: 'commerce_event', data };\n}\n\nexport interface BuildBatchOptions {\n ip?: string;\n sourceRequestId?: string;\n consent?: ConsentState;\n context?: Record<string, unknown>;\n}\n\n/**\n * Assembles the batch envelope wrapping events + identity + environment.\n */\nexport function buildBatch(\n events: MParticleEvent[],\n userIdentities: Record<string, string | number> | undefined,\n userAttributes: Record<string, unknown> | undefined,\n environment: Environment,\n options: BuildBatchOptions = {},\n): MParticleBatch {\n const batch: MParticleBatch = {\n events,\n environment,\n };\n if (userIdentities && Object.keys(userIdentities).length > 0)\n batch.user_identities = userIdentities;\n if (userAttributes && Object.keys(userAttributes).length > 0)\n batch.user_attributes = userAttributes;\n if (options.ip) batch.ip = options.ip;\n if (options.sourceRequestId)\n batch.source_request_id = options.sourceRequestId;\n if (options.consent) batch.consent_state = options.consent;\n if (options.context) batch.context = options.context;\n return batch;\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\n\n/**\n * mParticle data pod. Determines the regional endpoint used for the Events\n * API. Defaults to `us1`. See {@link buildEndpoint} in `batch.ts`.\n */\nexport type Pod = 'us1' | 'us2' | 'eu1' | 'au1';\n\n/**\n * mParticle environment for the batch. `production` routes to production\n * data streams; `development` sends to debug/verify streams.\n */\nexport type Environment = 'production' | 'development';\n\n/**\n * Event type used for the outgoing mParticle event. Defaults to\n * `custom_event` when not explicitly mapped via rule settings.\n */\nexport type EventType = 'custom_event' | 'screen_view' | 'commerce_event';\n\n/**\n * mParticle custom event type (category) for `custom_event`s. Defaults to\n * `other` when not specified.\n */\nexport type CustomEventType =\n | 'navigation'\n | 'location'\n | 'search'\n | 'transaction'\n | 'user_content'\n | 'user_preference'\n | 'social'\n | 'media'\n | 'attribution'\n | 'other';\n\n/**\n * mParticle product action verbs for commerce events.\n */\nexport type ProductActionType =\n | 'add_to_cart'\n | 'remove_from_cart'\n | 'checkout'\n | 'checkout_option'\n | 'click'\n | 'view_detail'\n | 'purchase'\n | 'refund'\n | 'add_to_wishlist'\n | 'remove_from_wishlist';\n\nexport interface Settings {\n /** mParticle input feed API key. */\n apiKey: string;\n /** mParticle input feed API secret. */\n apiSecret: string;\n /** Data pod selecting the regional endpoint. Default: `us1`. */\n pod?: Pod;\n /** Environment the batch targets. Default: `production`. */\n environment?: Environment;\n /**\n * Mapping that resolves to `user_identities` per batch. Each entry value\n * is a walkerOS mapping value; the resolved object is placed into the\n * mParticle batch `user_identities` envelope.\n */\n userIdentities?: WalkerOSMapping.Map;\n /**\n * Mapping that resolves to `user_attributes` per batch.\n */\n userAttributes?: WalkerOSMapping.Value;\n /**\n * Optional static consent state passthrough — shape is forwarded verbatim\n * to `consent_state` on the batch.\n */\n consent?: ConsentState;\n /** walkerOS mapping value resolving to the client IP for the batch. */\n ip?: WalkerOSMapping.Value;\n /**\n * Optional request correlation id. When omitted, falls back to `event.id`.\n */\n sourceRequestId?: WalkerOSMapping.Value;\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Determines which mParticle event shape is\n * produced for this walkerOS event and allows per-event identity overrides.\n */\nexport interface Mapping {\n /** Event type. Default: `custom_event`. */\n eventType?: EventType;\n /** Custom event type category for `custom_event`. Default: `other`. */\n customEventType?: CustomEventType;\n /** Commerce mapping resolving to ProductAction and related fields. */\n commerce?: WalkerOSMapping.Value;\n /** Per-event override for `user_identities`. Merged over settings. */\n userIdentities?: WalkerOSMapping.Map;\n /** Per-event override for `user_attributes`. */\n userAttributes?: WalkerOSMapping.Value;\n}\n\nexport interface Env extends DestinationServer.Env {\n sendServer?: typeof sendServer;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination 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>;\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n/**\n * Top-level mParticle batch payload posted to\n * `https://s2s.{pod}.mparticle.com/v2/events`.\n * https://docs.mparticle.com/developers/server/http/\n */\nexport interface MParticleBatch {\n events: MParticleEvent[];\n user_identities?: Record<string, string | number>;\n user_attributes?: Record<string, unknown>;\n environment: Environment;\n schema_version?: number;\n ip?: string;\n source_request_id?: string;\n consent_state?: ConsentState;\n context?: Record<string, unknown>;\n}\n\nexport type MParticleEvent =\n | { event_type: 'custom_event'; data: CustomEventData }\n | { event_type: 'screen_view'; data: ScreenViewEventData }\n | { event_type: 'commerce_event'; data: CommerceEventData };\n\nexport interface CommonEventData {\n timestamp_unixtime_ms?: number;\n source_message_id?: string;\n session_uuid?: string;\n custom_attributes?: Record<string, unknown>;\n custom_flags?: Record<string, unknown>;\n location?: Record<string, unknown>;\n}\n\nexport interface CustomEventData extends CommonEventData {\n event_name: string;\n custom_event_type: CustomEventType;\n}\n\nexport interface ScreenViewEventData extends CommonEventData {\n screen_name?: string;\n}\n\nexport interface CommerceEventData extends CommonEventData {\n product_action?: ProductAction;\n promotion_action?: PromotionAction;\n product_impressions?: ProductImpression[];\n currency_code?: string;\n is_non_interactive?: boolean;\n}\n\nexport interface ProductAction {\n action: ProductActionType;\n transaction_id?: string;\n total_amount?: number;\n tax_amount?: number;\n shipping_amount?: number;\n coupon_code?: string;\n affiliation?: string;\n checkout_step?: number;\n checkout_options?: string;\n products?: Product[];\n}\n\nexport interface Product {\n id?: string;\n name?: string;\n brand?: string;\n category?: string;\n variant?: string;\n position?: number;\n price?: number;\n quantity?: number;\n coupon_code?: string;\n total_product_amount?: number;\n custom_attributes?: Record<string, unknown>;\n}\n\nexport interface PromotionAction {\n action: 'view' | 'click';\n promotions?: Array<{\n id?: string;\n name?: string;\n creative?: string;\n position?: string;\n }>;\n}\n\nexport interface ProductImpression {\n product_impression_list?: string;\n products?: Product[];\n}\n\n/**\n * mParticle consent state envelope forwarded verbatim on the batch.\n * https://docs.mparticle.com/developers/server/http/#consent-state\n */\nexport interface ConsentState {\n gdpr?: Record<string, GDPRConsentState>;\n ccpa?: { data_sale_opt_out?: CCPAConsentState };\n}\n\nexport interface GDPRConsentState {\n consented: boolean;\n document?: string;\n timestamp_unixtime_ms?: number;\n location?: string;\n hardware_id?: string;\n}\n\nexport interface CCPAConsentState {\n consented: boolean;\n document?: string;\n timestamp_unixtime_ms?: number;\n location?: string;\n hardware_id?: string;\n}\n","import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationMParticle from './types';\n\nexport const destinationMParticle: Destination = {\n type: 'mparticle',\n\n config: {},\n\n async init({ config: partialConfig, logger }) {\n const config = getConfig(partialConfig, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationMParticle;\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$meta": {
3
3
  "package": "@walkeros/server-destination-mparticle",
4
- "version": "4.0.0-next-1777463920154",
4
+ "version": "4.0.0",
5
5
  "type": "destination",
6
6
  "platform": [
7
7
  "server"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@walkeros/server-destination-mparticle",
3
3
  "description": "mParticle server destination for walkerOS",
4
- "version": "4.0.0-next-1777463920154",
4
+ "version": "4.0.0",
5
5
  "license": "MIT",
6
6
  "exports": {
7
7
  ".": {
@@ -34,11 +34,11 @@
34
34
  "update": "npx npm-check-updates -u && npm update"
35
35
  },
36
36
  "dependencies": {
37
- "@walkeros/core": "4.0.0-next-1777463920154",
38
- "@walkeros/server-core": "4.0.0-next-1777463920154"
37
+ "@walkeros/core": "4.0.0",
38
+ "@walkeros/server-core": "4.0.0"
39
39
  },
40
40
  "devDependencies": {
41
- "@walkeros/collector": "4.0.0-next-1777463920154"
41
+ "@walkeros/collector": "4.0.0"
42
42
  },
43
43
  "repository": {
44
44
  "url": "git+https://github.com/elbwalker/walkerOS.git",