@walkeros/server-destination-klaviyo 3.4.2 → 4.0.0-next-1777463920154

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,7 +44,7 @@ npm install @walkeros/server-destination-klaviyo
44
44
 
45
45
  Per-event mapping settings control additional behavior:
46
46
 
47
- | Setting | Effect | Use with `skip: true` |
47
+ | Setting | Effect | Use with `silent: true` |
48
48
  | ---------- | ------------------------------------------ | ---------------------------- |
49
49
  | `identify` | Calls `createOrUpdateProfile()` | Yes, for login/signup events |
50
50
  | `value` | Sets revenue value + currency on the event | No |
package/dist/dev.d.mts CHANGED
@@ -94,12 +94,12 @@ declare namespace env {
94
94
  * At push time, the destination invokes the `klaviyo-api` SDK. The public
95
95
  * method paths users see on the client are:
96
96
  *
97
- * - `eventsApi.createEvent(body)` fires a metric event with inline profile
98
- * - `profilesApi.createOrUpdateProfile(body)` upserts a profile
97
+ * - `eventsApi.createEvent(body)` - fires a metric event with inline profile
98
+ * - `profilesApi.createOrUpdateProfile(body)` - upserts a profile
99
99
  *
100
100
  * Each `out` is therefore `[['method.path', ...args], ...]` matching the
101
101
  * actual SDK call order. `identify` fires before the event. When the rule
102
- * uses `skip: true` or `ignore: true`, `out` is `[]` or the identify-only
102
+ * uses `silent: true` or `ignore: true`, `out` is `[]` or the identify-only
103
103
  * list.
104
104
  */
105
105
  /**
@@ -124,7 +124,7 @@ declare const mappedEventName: KlaviyoStepExample;
124
124
  */
125
125
  declare const revenueEvent: KlaviyoStepExample;
126
126
  /**
127
- * Per-event identify with skip -- user login fires
127
+ * Per-event identify with silent -- user login fires
128
128
  * profilesApi.createOrUpdateProfile() only, no event tracked.
129
129
  */
130
130
  declare const userLoginIdentify: KlaviyoStepExample;
package/dist/dev.d.ts CHANGED
@@ -94,12 +94,12 @@ declare namespace env {
94
94
  * At push time, the destination invokes the `klaviyo-api` SDK. The public
95
95
  * method paths users see on the client are:
96
96
  *
97
- * - `eventsApi.createEvent(body)` fires a metric event with inline profile
98
- * - `profilesApi.createOrUpdateProfile(body)` upserts a profile
97
+ * - `eventsApi.createEvent(body)` - fires a metric event with inline profile
98
+ * - `profilesApi.createOrUpdateProfile(body)` - upserts a profile
99
99
  *
100
100
  * Each `out` is therefore `[['method.path', ...args], ...]` matching the
101
101
  * actual SDK call order. `identify` fires before the event. When the rule
102
- * uses `skip: true` or `ignore: true`, `out` is `[]` or the identify-only
102
+ * uses `silent: true` or `ignore: true`, `out` is `[]` or the identify-only
103
103
  * list.
104
104
  */
105
105
  /**
@@ -124,7 +124,7 @@ declare const mappedEventName: KlaviyoStepExample;
124
124
  */
125
125
  declare const revenueEvent: KlaviyoStepExample;
126
126
  /**
127
- * Per-event identify with skip -- user login fires
127
+ * Per-event identify with silent -- user login fires
128
128
  * profilesApi.createOrUpdateProfile() only, no event tracked.
129
129
  */
130
130
  declare const userLoginIdentify: KlaviyoStepExample;
package/dist/dev.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e,t=Object.defineProperty,a=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,r=Object.prototype.hasOwnProperty,n=(e,a)=>{for(var i in a)t(e,i,{get:a[i],enumerable:!0})},o={};n(o,{examples:()=>f,schemas:()=>s}),module.exports=(e=o,((e,n,o,s)=>{if(n&&"object"==typeof n||"function"==typeof n)for(let p of i(n))r.call(e,p)||p===o||t(e,p,{get:()=>n[p],enumerable:!(s=a(n,p))||s.enumerable});return e})(t({},"__esModule",{value:!0}),e));var s={};n(s,{MappingSchema:()=>d,SettingsSchema:()=>m,mapping:()=>v,settings:()=>c});var p=require("@walkeros/core/dev"),l=require("@walkeros/core/dev"),m=l.z.object({apiKey:l.z.string().min(1).describe("Klaviyo private API key. Starts with pk_. Find it under Settings > API Keys in your Klaviyo account."),email:l.z.string().describe("walkerOS mapping value path to resolve email from each event (like user.email).").optional(),phoneNumber:l.z.string().describe("walkerOS mapping value path to resolve phone number in E.164 format from each event.").optional(),externalId:l.z.string().describe("walkerOS mapping value path to resolve external ID from each event (like user.id).").optional(),identify:l.z.unknown().describe("Destination-level identity mapping. Resolves to profile attributes { firstName?, lastName?, organization?, properties? }. Fires createOrUpdateProfile() on first push and re-fires when values change.").optional(),currency:l.z.string().length(3).describe("Default ISO 4217 currency code for revenue events (like USD, EUR). Sets valueCurrency on Klaviyo events.").optional()}),u=require("@walkeros/core/dev"),d=u.z.object({identify:u.z.unknown().describe("Per-event identify mapping. Resolves to profile attributes for createOrUpdateProfile(). Use with rule-level skip: true on login/signup events.").optional(),value:u.z.unknown().describe("Revenue value mapping. Resolves to a numeric value for Klaviyo revenue tracking. Sets the value property and valueCurrency on the event.").optional()}),c=(0,p.zodToSchema)(m),v=(0,p.zodToSchema)(d),f={};n(f,{env:()=>g,step:()=>h});var g={};n(g,{push:()=>b,simulation:()=>w});var y=()=>Promise.resolve({});var b={eventsApi:{createEvent:y},profilesApi:{createOrUpdateProfile:y}},w=["call:eventsApi.createEvent","call:profilesApi.createOrUpdateProfile"],h={};n(h,{defaultEvent:()=>P,destinationIdentify:()=>N,emailOnly:()=>A,mappedEventName:()=>I,revenueEvent:()=>S,userLoginIdentify:()=>x,wildcardIgnored:()=>E});var O=require("@walkeros/core"),P={title:"Default event",description:"An event is sent to Klaviyo as a metric with an inline profile resolved from the user email and id.",in:(0,O.getEvent)("product view",{timestamp:1700000100,user:{id:"us3r",email:"user@example.com"}}),out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"product view"}}},properties:{},time:new Date(1700000100).toISOString()}}}]]},I={title:"Viewed product",description:"A product view is mapped to the Klaviyo Viewed Product metric with properties such as product name and price.",in:(0,O.getEvent)("product view",{timestamp:1700000101,user:{id:"us3r",email:"user@example.com"},data:{name:"USB Cable",id:"PROD-1",price:9.99}}),mapping:{name:"Viewed Product",data:{map:{ProductName:"data.name",ProductID:"data.id",Price:"data.price"}}},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"Viewed Product"}}},properties:{ProductName:"USB Cable",ProductID:"PROD-1",Price:9.99},time:new Date(1700000101).toISOString()}}}]]},S={title:"Placed order",description:"An order complete is sent to Klaviyo as Placed Order with value and currency for revenue attribution.",in:(0,O.getEvent)("order complete",{timestamp:1700000102,user:{id:"us3r",email:"user@example.com"},data:{id:"ORD-123",total:99.99,itemNames:["Widget A","Widget B"]}}),settings:{currency:"EUR"},mapping:{name:"Placed Order",data:{map:{OrderId:"data.id",value:"data.total",ItemNames:"data.itemNames"}},settings:{value:"data.total"}},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"Placed Order"}}},properties:{OrderId:"ORD-123",value:99.99,ItemNames:["Widget A","Widget B"]},time:new Date(1700000102).toISOString(),valueCurrency:"EUR"}}}]]},x={title:"User login identify",description:"A user login upserts the Klaviyo profile with name, organization, and custom properties without firing an event.",in:(0,O.getEvent)("user login",{timestamp:1700000103,user:{id:"us3r",email:"user@acme.com"},data:{firstName:"Jane",lastName:"Doe",company:"Acme Corp",plan:"premium"}}),mapping:{skip:!0,settings:{identify:{map:{firstName:"data.firstName",lastName:"data.lastName",organization:"data.company",properties:{map:{plan:"data.plan"}}}}}},out:[["profilesApi.createOrUpdateProfile",{data:{type:"profile",attributes:{email:"user@acme.com",externalId:"us3r",firstName:"Jane",lastName:"Doe",organization:"Acme Corp",properties:{plan:"premium"}}}}]]},N={title:"Destination identify",description:"Destination-level identify upserts the Klaviyo profile with a first name before each event is sent.",in:(0,O.getEvent)("page view",{timestamp:1700000104,user:{id:"us3r",email:"user@example.com",firstName:"Jane"}}),settings:{identify:{map:{firstName:"user.firstName"}}},out:[["profilesApi.createOrUpdateProfile",{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r",firstName:"Jane"}}}],["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"page view"}}},properties:{},time:new Date(1700000104).toISOString()}}}]]},A={title:"Email only",description:"A newsletter signup uses only the email address as the Klaviyo profile identifier, with no external id.",in:(0,O.getEvent)("newsletter signup",{timestamp:1700000105,user:{email:"subscriber@example.com"}}),settings:{externalId:void 0},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"subscriber@example.com"}}},metric:{data:{type:"metric",attributes:{name:"newsletter signup"}}},properties:{},time:new Date(1700000105).toISOString()}}}]]},E={public:!1,in:(0,O.getEvent)("debug noise",{timestamp:1700000106,user:{id:"us3r",email:"user@example.com"}}),mapping:{ignore:!0},out:[]};//# sourceMappingURL=dev.js.map
1
+ "use strict";var e,t=Object.defineProperty,a=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,r=Object.prototype.hasOwnProperty,n=(e,a)=>{for(var i in a)t(e,i,{get:a[i],enumerable:!0})},o={};n(o,{examples:()=>f,schemas:()=>s}),module.exports=(e=o,((e,n,o,s)=>{if(n&&"object"==typeof n||"function"==typeof n)for(let p of i(n))r.call(e,p)||p===o||t(e,p,{get:()=>n[p],enumerable:!(s=a(n,p))||s.enumerable});return e})(t({},"__esModule",{value:!0}),e));var s={};n(s,{MappingSchema:()=>d,SettingsSchema:()=>m,mapping:()=>v,settings:()=>c});var p=require("@walkeros/core/dev"),l=require("@walkeros/core/dev"),m=l.z.object({apiKey:l.z.string().min(1).describe("Klaviyo private API key. Starts with pk_. Find it under Settings > API Keys in your Klaviyo account."),email:l.z.string().describe("walkerOS mapping value path to resolve email from each event (like user.email).").optional(),phoneNumber:l.z.string().describe("walkerOS mapping value path to resolve phone number in E.164 format from each event.").optional(),externalId:l.z.string().describe("walkerOS mapping value path to resolve external ID from each event (like user.id).").optional(),identify:l.z.unknown().describe("Destination-level identity mapping. Resolves to profile attributes { firstName?, lastName?, organization?, properties? }. Fires createOrUpdateProfile() on first push and re-fires when values change.").optional(),currency:l.z.string().length(3).describe("Default ISO 4217 currency code for revenue events (like USD, EUR). Sets valueCurrency on Klaviyo events.").optional()}),u=require("@walkeros/core/dev"),d=u.z.object({identify:u.z.unknown().describe("Per-event identify mapping. Resolves to profile attributes for createOrUpdateProfile(). Use with rule-level silent: true on login/signup events.").optional(),value:u.z.unknown().describe("Revenue value mapping. Resolves to a numeric value for Klaviyo revenue tracking. Sets the value property and valueCurrency on the event.").optional()}),c=(0,p.zodToSchema)(m),v=(0,p.zodToSchema)(d),f={};n(f,{env:()=>g,step:()=>h});var g={};n(g,{push:()=>b,simulation:()=>w});var y=()=>Promise.resolve({});var b={eventsApi:{createEvent:y},profilesApi:{createOrUpdateProfile:y}},w=["call:eventsApi.createEvent","call:profilesApi.createOrUpdateProfile"],h={};n(h,{defaultEvent:()=>P,destinationIdentify:()=>N,emailOnly:()=>A,mappedEventName:()=>I,revenueEvent:()=>S,userLoginIdentify:()=>x,wildcardIgnored:()=>E});var O=require("@walkeros/core"),P={title:"Default event",description:"An event is sent to Klaviyo as a metric with an inline profile resolved from the user email and id.",in:(0,O.getEvent)("product view",{timestamp:1700000100,user:{id:"us3r",email:"user@example.com"}}),out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"product view"}}},properties:{},time:new Date(1700000100).toISOString()}}}]]},I={title:"Viewed product",description:"A product view is mapped to the Klaviyo Viewed Product metric with properties such as product name and price.",in:(0,O.getEvent)("product view",{timestamp:1700000101,user:{id:"us3r",email:"user@example.com"},data:{name:"USB Cable",id:"PROD-1",price:9.99}}),mapping:{name:"Viewed Product",data:{map:{ProductName:"data.name",ProductID:"data.id",Price:"data.price"}}},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"Viewed Product"}}},properties:{ProductName:"USB Cable",ProductID:"PROD-1",Price:9.99},time:new Date(1700000101).toISOString()}}}]]},S={title:"Placed order",description:"An order complete is sent to Klaviyo as Placed Order with value and currency for revenue attribution.",in:(0,O.getEvent)("order complete",{timestamp:1700000102,user:{id:"us3r",email:"user@example.com"},data:{id:"ORD-123",total:99.99,itemNames:["Widget A","Widget B"]}}),settings:{currency:"EUR"},mapping:{name:"Placed Order",data:{map:{OrderId:"data.id",value:"data.total",ItemNames:"data.itemNames"}},settings:{value:"data.total"}},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"Placed Order"}}},properties:{OrderId:"ORD-123",value:99.99,ItemNames:["Widget A","Widget B"]},time:new Date(1700000102).toISOString(),valueCurrency:"EUR"}}}]]},x={title:"User login identify",description:"A user login upserts the Klaviyo profile with name, organization, and custom properties without firing an event.",in:(0,O.getEvent)("user login",{timestamp:1700000103,user:{id:"us3r",email:"user@acme.com"},data:{firstName:"Jane",lastName:"Doe",company:"Acme Corp",plan:"premium"}}),mapping:{silent:!0,settings:{identify:{map:{firstName:"data.firstName",lastName:"data.lastName",organization:"data.company",properties:{map:{plan:"data.plan"}}}}}},out:[["profilesApi.createOrUpdateProfile",{data:{type:"profile",attributes:{email:"user@acme.com",externalId:"us3r",firstName:"Jane",lastName:"Doe",organization:"Acme Corp",properties:{plan:"premium"}}}}]]},N={title:"Destination identify",description:"Destination-level identify upserts the Klaviyo profile with a first name before each event is sent.",in:(0,O.getEvent)("page view",{timestamp:1700000104,user:{id:"us3r",email:"user@example.com",firstName:"Jane"}}),settings:{identify:{map:{firstName:"user.firstName"}}},out:[["profilesApi.createOrUpdateProfile",{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r",firstName:"Jane"}}}],["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"page view"}}},properties:{},time:new Date(1700000104).toISOString()}}}]]},A={title:"Email only",description:"A newsletter signup uses only the email address as the Klaviyo profile identifier, with no external id.",in:(0,O.getEvent)("newsletter signup",{timestamp:1700000105,user:{email:"subscriber@example.com"}}),settings:{externalId:void 0},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"subscriber@example.com"}}},metric:{data:{type:"metric",attributes:{name:"newsletter signup"}}},properties:{},time:new Date(1700000105).toISOString()}}}]]},E={public:!1,in:(0,O.getEvent)("debug noise",{timestamp:1700000106,user:{id:"us3r",email:"user@example.com"}}),mapping:{ignore:!0},out:[]};//# sourceMappingURL=dev.js.map
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n apiKey: z\n .string()\n .min(1)\n .describe(\n 'Klaviyo private API key. Starts with pk_. Find it under Settings > API Keys in your Klaviyo account.',\n ),\n email: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve email from each event (like user.email).',\n )\n .optional(),\n phoneNumber: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve phone number in E.164 format from each event.',\n )\n .optional(),\n externalId: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve external ID from each event (like user.id).',\n )\n .optional(),\n identify: z\n .unknown()\n .describe(\n 'Destination-level identity mapping. Resolves to profile attributes { firstName?, lastName?, organization?, properties? }. Fires createOrUpdateProfile() on first push and re-fires when values change.',\n )\n .optional(),\n currency: z\n .string()\n .length(3)\n .describe(\n 'Default ISO 4217 currency code for revenue events (like USD, EUR). Sets valueCurrency on Klaviyo events.',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z.object({\n identify: z\n .unknown()\n .describe(\n 'Per-event identify mapping. Resolves to profile attributes for createOrUpdateProfile(). Use with rule-level skip: true on login/signup events.',\n )\n .optional(),\n value: z\n .unknown()\n .describe(\n 'Revenue value mapping. Resolves to a numeric value for Klaviyo revenue tracking. Sets the value property and valueCurrency on the event.',\n )\n .optional(),\n});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type {\n Env,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from '../types';\n\nconst asyncNoop = () => Promise.resolve({});\n\nfunction createMockEventsApi(): KlaviyoEventsApiMock {\n return {\n createEvent: asyncNoop,\n };\n}\n\nfunction createMockProfilesApi(): KlaviyoProfilesApiMock {\n return {\n createOrUpdateProfile: asyncNoop,\n };\n}\n\nexport const push: Env = {\n eventsApi: createMockEventsApi(),\n profilesApi: createMockProfilesApi(),\n};\n\nexport const simulation = [\n 'call:eventsApi.createEvent',\n 'call:profilesApi.createOrUpdateProfile',\n];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Settings } from '../types';\n\n/**\n * Klaviyo SDK step examples.\n *\n * At push time, the destination invokes the `klaviyo-api` SDK. The public\n * method paths users see on the client are:\n *\n * - `eventsApi.createEvent(body)` — fires a metric event with inline profile\n * - `profilesApi.createOrUpdateProfile(body)` — upserts a profile\n *\n * Each `out` is therefore `[['method.path', ...args], ...]` matching the\n * actual SDK call order. `identify` fires before the event. When the rule\n * uses `skip: true` or `ignore: true`, `out` is `[]` or the identify-only\n * list.\n */\n\n/**\n * Extended step example that may carry destination-level settings overrides.\n */\nexport type KlaviyoStepExample = Flow.StepExample & {\n settings?: Partial<Settings>;\n};\n\n/**\n * Default event forwarding -- eventsApi.createEvent() with event name and\n * inline profile. Email resolved from default settings.email = 'user.email'.\n */\nexport const defaultEvent: KlaviyoStepExample = {\n title: 'Default event',\n description:\n 'An event is sent to Klaviyo as a metric with an inline profile resolved from the user email and id.',\n in: getEvent('product view', {\n timestamp: 1700000100,\n user: { id: 'us3r', email: 'user@example.com' },\n }),\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'product view' },\n },\n },\n properties: {},\n time: new Date(1700000100).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Mapped event name -- mapping.name renames the event to Klaviyo's expected\n * metric name for ecommerce reporting.\n */\nexport const mappedEventName: KlaviyoStepExample = {\n title: 'Viewed product',\n description:\n 'A product view is mapped to the Klaviyo Viewed Product metric with properties such as product name and price.',\n in: getEvent('product view', {\n timestamp: 1700000101,\n user: { id: 'us3r', email: 'user@example.com' },\n data: {\n name: 'USB Cable',\n id: 'PROD-1',\n price: 9.99,\n },\n }),\n mapping: {\n name: 'Viewed Product',\n data: {\n map: {\n ProductName: 'data.name',\n ProductID: 'data.id',\n Price: 'data.price',\n },\n },\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'Viewed Product' },\n },\n },\n properties: {\n ProductName: 'USB Cable',\n ProductID: 'PROD-1',\n Price: 9.99,\n },\n time: new Date(1700000101).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Revenue event -- order complete with value mapping. Sets $value and\n * valueCurrency on the Klaviyo event for revenue tracking.\n */\nexport const revenueEvent: KlaviyoStepExample = {\n title: 'Placed order',\n description:\n 'An order complete is sent to Klaviyo as Placed Order with value and currency for revenue attribution.',\n in: getEvent('order complete', {\n timestamp: 1700000102,\n user: { id: 'us3r', email: 'user@example.com' },\n data: {\n id: 'ORD-123',\n total: 99.99,\n itemNames: ['Widget A', 'Widget B'],\n },\n }),\n settings: {\n currency: 'EUR',\n },\n mapping: {\n name: 'Placed Order',\n data: {\n map: {\n OrderId: 'data.id',\n value: 'data.total',\n ItemNames: 'data.itemNames',\n },\n },\n settings: {\n value: 'data.total',\n },\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'Placed Order' },\n },\n },\n properties: {\n OrderId: 'ORD-123',\n value: 99.99,\n ItemNames: ['Widget A', 'Widget B'],\n },\n time: new Date(1700000102).toISOString(),\n valueCurrency: 'EUR',\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Per-event identify with skip -- user login fires\n * profilesApi.createOrUpdateProfile() only, no event tracked.\n */\nexport const userLoginIdentify: KlaviyoStepExample = {\n title: 'User login identify',\n description:\n 'A user login upserts the Klaviyo profile with name, organization, and custom properties without firing an event.',\n in: getEvent('user login', {\n timestamp: 1700000103,\n user: { id: 'us3r', email: 'user@acme.com' },\n data: {\n firstName: 'Jane',\n lastName: 'Doe',\n company: 'Acme Corp',\n plan: 'premium',\n },\n }),\n mapping: {\n skip: true,\n settings: {\n identify: {\n map: {\n firstName: 'data.firstName',\n lastName: 'data.lastName',\n organization: 'data.company',\n properties: {\n map: {\n plan: 'data.plan',\n },\n },\n },\n },\n },\n },\n out: [\n [\n 'profilesApi.createOrUpdateProfile',\n {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@acme.com',\n externalId: 'us3r',\n firstName: 'Jane',\n lastName: 'Doe',\n organization: 'Acme Corp',\n properties: {\n plan: 'premium',\n },\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Destination-level identify -- fires profilesApi.createOrUpdateProfile()\n * on first push when settings.identify resolves, then fires createEvent().\n */\nexport const destinationIdentify: KlaviyoStepExample = {\n title: 'Destination identify',\n description:\n 'Destination-level identify upserts the Klaviyo profile with a first name before each event is sent.',\n in: getEvent('page view', {\n timestamp: 1700000104,\n user: { id: 'us3r', email: 'user@example.com', firstName: 'Jane' },\n }),\n settings: {\n identify: {\n map: {\n firstName: 'user.firstName',\n },\n },\n },\n out: [\n [\n 'profilesApi.createOrUpdateProfile',\n {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n firstName: 'Jane',\n },\n },\n },\n ],\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'page view' },\n },\n },\n properties: {},\n time: new Date(1700000104).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Email only -- no externalId. Klaviyo accepts email as sole identifier.\n */\nexport const emailOnly: KlaviyoStepExample = {\n title: 'Email only',\n description:\n 'A newsletter signup uses only the email address as the Klaviyo profile identifier, with no external id.',\n in: getEvent('newsletter signup', {\n timestamp: 1700000105,\n user: { email: 'subscriber@example.com' },\n }),\n settings: {\n externalId: undefined,\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'subscriber@example.com',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'newsletter signup' },\n },\n },\n properties: {},\n time: new Date(1700000105).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Wildcard ignore -- the event matches a mapping rule with ignore: true.\n * The destination fires zero API calls.\n */\nexport const wildcardIgnored: KlaviyoStepExample = {\n public: false,\n in: getEvent('debug noise', {\n timestamp: 1700000106,\n user: { id: 'us3r', email: 'user@example.com' },\n }),\n mapping: { ignore: true },\n out: [],\n};\n"],"mappings":"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","names":["import_dev","import_dev"]}
1
+ {"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n apiKey: z\n .string()\n .min(1)\n .describe(\n 'Klaviyo private API key. Starts with pk_. Find it under Settings > API Keys in your Klaviyo account.',\n ),\n email: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve email from each event (like user.email).',\n )\n .optional(),\n phoneNumber: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve phone number in E.164 format from each event.',\n )\n .optional(),\n externalId: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve external ID from each event (like user.id).',\n )\n .optional(),\n identify: z\n .unknown()\n .describe(\n 'Destination-level identity mapping. Resolves to profile attributes { firstName?, lastName?, organization?, properties? }. Fires createOrUpdateProfile() on first push and re-fires when values change.',\n )\n .optional(),\n currency: z\n .string()\n .length(3)\n .describe(\n 'Default ISO 4217 currency code for revenue events (like USD, EUR). Sets valueCurrency on Klaviyo events.',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z.object({\n identify: z\n .unknown()\n .describe(\n 'Per-event identify mapping. Resolves to profile attributes for createOrUpdateProfile(). Use with rule-level silent: true on login/signup events.',\n )\n .optional(),\n value: z\n .unknown()\n .describe(\n 'Revenue value mapping. Resolves to a numeric value for Klaviyo revenue tracking. Sets the value property and valueCurrency on the event.',\n )\n .optional(),\n});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type {\n Env,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from '../types';\n\nconst asyncNoop = () => Promise.resolve({});\n\nfunction createMockEventsApi(): KlaviyoEventsApiMock {\n return {\n createEvent: asyncNoop,\n };\n}\n\nfunction createMockProfilesApi(): KlaviyoProfilesApiMock {\n return {\n createOrUpdateProfile: asyncNoop,\n };\n}\n\nexport const push: Env = {\n eventsApi: createMockEventsApi(),\n profilesApi: createMockProfilesApi(),\n};\n\nexport const simulation = [\n 'call:eventsApi.createEvent',\n 'call:profilesApi.createOrUpdateProfile',\n];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Settings } from '../types';\n\n/**\n * Klaviyo SDK step examples.\n *\n * At push time, the destination invokes the `klaviyo-api` SDK. The public\n * method paths users see on the client are:\n *\n * - `eventsApi.createEvent(body)` - fires a metric event with inline profile\n * - `profilesApi.createOrUpdateProfile(body)` - upserts a profile\n *\n * Each `out` is therefore `[['method.path', ...args], ...]` matching the\n * actual SDK call order. `identify` fires before the event. When the rule\n * uses `silent: true` or `ignore: true`, `out` is `[]` or the identify-only\n * list.\n */\n\n/**\n * Extended step example that may carry destination-level settings overrides.\n */\nexport type KlaviyoStepExample = Flow.StepExample & {\n settings?: Partial<Settings>;\n};\n\n/**\n * Default event forwarding -- eventsApi.createEvent() with event name and\n * inline profile. Email resolved from default settings.email = 'user.email'.\n */\nexport const defaultEvent: KlaviyoStepExample = {\n title: 'Default event',\n description:\n 'An event is sent to Klaviyo as a metric with an inline profile resolved from the user email and id.',\n in: getEvent('product view', {\n timestamp: 1700000100,\n user: { id: 'us3r', email: 'user@example.com' },\n }),\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'product view' },\n },\n },\n properties: {},\n time: new Date(1700000100).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Mapped event name -- mapping.name renames the event to Klaviyo's expected\n * metric name for ecommerce reporting.\n */\nexport const mappedEventName: KlaviyoStepExample = {\n title: 'Viewed product',\n description:\n 'A product view is mapped to the Klaviyo Viewed Product metric with properties such as product name and price.',\n in: getEvent('product view', {\n timestamp: 1700000101,\n user: { id: 'us3r', email: 'user@example.com' },\n data: {\n name: 'USB Cable',\n id: 'PROD-1',\n price: 9.99,\n },\n }),\n mapping: {\n name: 'Viewed Product',\n data: {\n map: {\n ProductName: 'data.name',\n ProductID: 'data.id',\n Price: 'data.price',\n },\n },\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'Viewed Product' },\n },\n },\n properties: {\n ProductName: 'USB Cable',\n ProductID: 'PROD-1',\n Price: 9.99,\n },\n time: new Date(1700000101).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Revenue event -- order complete with value mapping. Sets $value and\n * valueCurrency on the Klaviyo event for revenue tracking.\n */\nexport const revenueEvent: KlaviyoStepExample = {\n title: 'Placed order',\n description:\n 'An order complete is sent to Klaviyo as Placed Order with value and currency for revenue attribution.',\n in: getEvent('order complete', {\n timestamp: 1700000102,\n user: { id: 'us3r', email: 'user@example.com' },\n data: {\n id: 'ORD-123',\n total: 99.99,\n itemNames: ['Widget A', 'Widget B'],\n },\n }),\n settings: {\n currency: 'EUR',\n },\n mapping: {\n name: 'Placed Order',\n data: {\n map: {\n OrderId: 'data.id',\n value: 'data.total',\n ItemNames: 'data.itemNames',\n },\n },\n settings: {\n value: 'data.total',\n },\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'Placed Order' },\n },\n },\n properties: {\n OrderId: 'ORD-123',\n value: 99.99,\n ItemNames: ['Widget A', 'Widget B'],\n },\n time: new Date(1700000102).toISOString(),\n valueCurrency: 'EUR',\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Per-event identify with silent -- user login fires\n * profilesApi.createOrUpdateProfile() only, no event tracked.\n */\nexport const userLoginIdentify: KlaviyoStepExample = {\n title: 'User login identify',\n description:\n 'A user login upserts the Klaviyo profile with name, organization, and custom properties without firing an event.',\n in: getEvent('user login', {\n timestamp: 1700000103,\n user: { id: 'us3r', email: 'user@acme.com' },\n data: {\n firstName: 'Jane',\n lastName: 'Doe',\n company: 'Acme Corp',\n plan: 'premium',\n },\n }),\n mapping: {\n silent: true,\n settings: {\n identify: {\n map: {\n firstName: 'data.firstName',\n lastName: 'data.lastName',\n organization: 'data.company',\n properties: {\n map: {\n plan: 'data.plan',\n },\n },\n },\n },\n },\n },\n out: [\n [\n 'profilesApi.createOrUpdateProfile',\n {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@acme.com',\n externalId: 'us3r',\n firstName: 'Jane',\n lastName: 'Doe',\n organization: 'Acme Corp',\n properties: {\n plan: 'premium',\n },\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Destination-level identify -- fires profilesApi.createOrUpdateProfile()\n * on first push when settings.identify resolves, then fires createEvent().\n */\nexport const destinationIdentify: KlaviyoStepExample = {\n title: 'Destination identify',\n description:\n 'Destination-level identify upserts the Klaviyo profile with a first name before each event is sent.',\n in: getEvent('page view', {\n timestamp: 1700000104,\n user: { id: 'us3r', email: 'user@example.com', firstName: 'Jane' },\n }),\n settings: {\n identify: {\n map: {\n firstName: 'user.firstName',\n },\n },\n },\n out: [\n [\n 'profilesApi.createOrUpdateProfile',\n {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n firstName: 'Jane',\n },\n },\n },\n ],\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'page view' },\n },\n },\n properties: {},\n time: new Date(1700000104).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Email only -- no externalId. Klaviyo accepts email as sole identifier.\n */\nexport const emailOnly: KlaviyoStepExample = {\n title: 'Email only',\n description:\n 'A newsletter signup uses only the email address as the Klaviyo profile identifier, with no external id.',\n in: getEvent('newsletter signup', {\n timestamp: 1700000105,\n user: { email: 'subscriber@example.com' },\n }),\n settings: {\n externalId: undefined,\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'subscriber@example.com',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'newsletter signup' },\n },\n },\n properties: {},\n time: new Date(1700000105).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Wildcard ignore -- the event matches a mapping rule with ignore: true.\n * The destination fires zero API calls.\n */\nexport const wildcardIgnored: KlaviyoStepExample = {\n public: false,\n in: getEvent('debug noise', {\n timestamp: 1700000106,\n user: { id: 'us3r', email: 'user@example.com' },\n }),\n mapping: { ignore: true },\n out: [],\n};\n"],"mappings":"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","names":["import_dev","import_dev"]}
package/dist/dev.mjs CHANGED
@@ -1 +1 @@
1
- var e=Object.defineProperty,t=(t,a)=>{for(var i in a)e(t,i,{get:a[i],enumerable:!0})},a={};t(a,{MappingSchema:()=>o,SettingsSchema:()=>n,mapping:()=>l,settings:()=>p});import{zodToSchema as i}from"@walkeros/core/dev";import{z as r}from"@walkeros/core/dev";var n=r.object({apiKey:r.string().min(1).describe("Klaviyo private API key. Starts with pk_. Find it under Settings > API Keys in your Klaviyo account."),email:r.string().describe("walkerOS mapping value path to resolve email from each event (like user.email).").optional(),phoneNumber:r.string().describe("walkerOS mapping value path to resolve phone number in E.164 format from each event.").optional(),externalId:r.string().describe("walkerOS mapping value path to resolve external ID from each event (like user.id).").optional(),identify:r.unknown().describe("Destination-level identity mapping. Resolves to profile attributes { firstName?, lastName?, organization?, properties? }. Fires createOrUpdateProfile() on first push and re-fires when values change.").optional(),currency:r.string().length(3).describe("Default ISO 4217 currency code for revenue events (like USD, EUR). Sets valueCurrency on Klaviyo events.").optional()});import{z as s}from"@walkeros/core/dev";var o=s.object({identify:s.unknown().describe("Per-event identify mapping. Resolves to profile attributes for createOrUpdateProfile(). Use with rule-level skip: true on login/signup events.").optional(),value:s.unknown().describe("Revenue value mapping. Resolves to a numeric value for Klaviyo revenue tracking. Sets the value property and valueCurrency on the event.").optional()}),p=i(n),l=i(o),m={};t(m,{env:()=>d,step:()=>f});var d={};t(d,{push:()=>c,simulation:()=>v});var u=()=>Promise.resolve({});var c={eventsApi:{createEvent:u},profilesApi:{createOrUpdateProfile:u}},v=["call:eventsApi.createEvent","call:profilesApi.createOrUpdateProfile"],f={};t(f,{defaultEvent:()=>y,destinationIdentify:()=>I,emailOnly:()=>O,mappedEventName:()=>b,revenueEvent:()=>w,userLoginIdentify:()=>h,wildcardIgnored:()=>P});import{getEvent as g}from"@walkeros/core";var y={title:"Default event",description:"An event is sent to Klaviyo as a metric with an inline profile resolved from the user email and id.",in:g("product view",{timestamp:1700000100,user:{id:"us3r",email:"user@example.com"}}),out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"product view"}}},properties:{},time:new Date(1700000100).toISOString()}}}]]},b={title:"Viewed product",description:"A product view is mapped to the Klaviyo Viewed Product metric with properties such as product name and price.",in:g("product view",{timestamp:1700000101,user:{id:"us3r",email:"user@example.com"},data:{name:"USB Cable",id:"PROD-1",price:9.99}}),mapping:{name:"Viewed Product",data:{map:{ProductName:"data.name",ProductID:"data.id",Price:"data.price"}}},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"Viewed Product"}}},properties:{ProductName:"USB Cable",ProductID:"PROD-1",Price:9.99},time:new Date(1700000101).toISOString()}}}]]},w={title:"Placed order",description:"An order complete is sent to Klaviyo as Placed Order with value and currency for revenue attribution.",in:g("order complete",{timestamp:1700000102,user:{id:"us3r",email:"user@example.com"},data:{id:"ORD-123",total:99.99,itemNames:["Widget A","Widget B"]}}),settings:{currency:"EUR"},mapping:{name:"Placed Order",data:{map:{OrderId:"data.id",value:"data.total",ItemNames:"data.itemNames"}},settings:{value:"data.total"}},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"Placed Order"}}},properties:{OrderId:"ORD-123",value:99.99,ItemNames:["Widget A","Widget B"]},time:new Date(1700000102).toISOString(),valueCurrency:"EUR"}}}]]},h={title:"User login identify",description:"A user login upserts the Klaviyo profile with name, organization, and custom properties without firing an event.",in:g("user login",{timestamp:1700000103,user:{id:"us3r",email:"user@acme.com"},data:{firstName:"Jane",lastName:"Doe",company:"Acme Corp",plan:"premium"}}),mapping:{skip:!0,settings:{identify:{map:{firstName:"data.firstName",lastName:"data.lastName",organization:"data.company",properties:{map:{plan:"data.plan"}}}}}},out:[["profilesApi.createOrUpdateProfile",{data:{type:"profile",attributes:{email:"user@acme.com",externalId:"us3r",firstName:"Jane",lastName:"Doe",organization:"Acme Corp",properties:{plan:"premium"}}}}]]},I={title:"Destination identify",description:"Destination-level identify upserts the Klaviyo profile with a first name before each event is sent.",in:g("page view",{timestamp:1700000104,user:{id:"us3r",email:"user@example.com",firstName:"Jane"}}),settings:{identify:{map:{firstName:"user.firstName"}}},out:[["profilesApi.createOrUpdateProfile",{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r",firstName:"Jane"}}}],["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"page view"}}},properties:{},time:new Date(1700000104).toISOString()}}}]]},O={title:"Email only",description:"A newsletter signup uses only the email address as the Klaviyo profile identifier, with no external id.",in:g("newsletter signup",{timestamp:1700000105,user:{email:"subscriber@example.com"}}),settings:{externalId:void 0},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"subscriber@example.com"}}},metric:{data:{type:"metric",attributes:{name:"newsletter signup"}}},properties:{},time:new Date(1700000105).toISOString()}}}]]},P={public:!1,in:g("debug noise",{timestamp:1700000106,user:{id:"us3r",email:"user@example.com"}}),mapping:{ignore:!0},out:[]};export{m as examples,a as schemas};//# sourceMappingURL=dev.mjs.map
1
+ var e=Object.defineProperty,t=(t,a)=>{for(var i in a)e(t,i,{get:a[i],enumerable:!0})},a={};t(a,{MappingSchema:()=>o,SettingsSchema:()=>n,mapping:()=>l,settings:()=>p});import{zodToSchema as i}from"@walkeros/core/dev";import{z as r}from"@walkeros/core/dev";var n=r.object({apiKey:r.string().min(1).describe("Klaviyo private API key. Starts with pk_. Find it under Settings > API Keys in your Klaviyo account."),email:r.string().describe("walkerOS mapping value path to resolve email from each event (like user.email).").optional(),phoneNumber:r.string().describe("walkerOS mapping value path to resolve phone number in E.164 format from each event.").optional(),externalId:r.string().describe("walkerOS mapping value path to resolve external ID from each event (like user.id).").optional(),identify:r.unknown().describe("Destination-level identity mapping. Resolves to profile attributes { firstName?, lastName?, organization?, properties? }. Fires createOrUpdateProfile() on first push and re-fires when values change.").optional(),currency:r.string().length(3).describe("Default ISO 4217 currency code for revenue events (like USD, EUR). Sets valueCurrency on Klaviyo events.").optional()});import{z as s}from"@walkeros/core/dev";var o=s.object({identify:s.unknown().describe("Per-event identify mapping. Resolves to profile attributes for createOrUpdateProfile(). Use with rule-level silent: true on login/signup events.").optional(),value:s.unknown().describe("Revenue value mapping. Resolves to a numeric value for Klaviyo revenue tracking. Sets the value property and valueCurrency on the event.").optional()}),p=i(n),l=i(o),m={};t(m,{env:()=>d,step:()=>f});var d={};t(d,{push:()=>c,simulation:()=>v});var u=()=>Promise.resolve({});var c={eventsApi:{createEvent:u},profilesApi:{createOrUpdateProfile:u}},v=["call:eventsApi.createEvent","call:profilesApi.createOrUpdateProfile"],f={};t(f,{defaultEvent:()=>y,destinationIdentify:()=>I,emailOnly:()=>O,mappedEventName:()=>b,revenueEvent:()=>w,userLoginIdentify:()=>h,wildcardIgnored:()=>P});import{getEvent as g}from"@walkeros/core";var y={title:"Default event",description:"An event is sent to Klaviyo as a metric with an inline profile resolved from the user email and id.",in:g("product view",{timestamp:1700000100,user:{id:"us3r",email:"user@example.com"}}),out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"product view"}}},properties:{},time:new Date(1700000100).toISOString()}}}]]},b={title:"Viewed product",description:"A product view is mapped to the Klaviyo Viewed Product metric with properties such as product name and price.",in:g("product view",{timestamp:1700000101,user:{id:"us3r",email:"user@example.com"},data:{name:"USB Cable",id:"PROD-1",price:9.99}}),mapping:{name:"Viewed Product",data:{map:{ProductName:"data.name",ProductID:"data.id",Price:"data.price"}}},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"Viewed Product"}}},properties:{ProductName:"USB Cable",ProductID:"PROD-1",Price:9.99},time:new Date(1700000101).toISOString()}}}]]},w={title:"Placed order",description:"An order complete is sent to Klaviyo as Placed Order with value and currency for revenue attribution.",in:g("order complete",{timestamp:1700000102,user:{id:"us3r",email:"user@example.com"},data:{id:"ORD-123",total:99.99,itemNames:["Widget A","Widget B"]}}),settings:{currency:"EUR"},mapping:{name:"Placed Order",data:{map:{OrderId:"data.id",value:"data.total",ItemNames:"data.itemNames"}},settings:{value:"data.total"}},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"Placed Order"}}},properties:{OrderId:"ORD-123",value:99.99,ItemNames:["Widget A","Widget B"]},time:new Date(1700000102).toISOString(),valueCurrency:"EUR"}}}]]},h={title:"User login identify",description:"A user login upserts the Klaviyo profile with name, organization, and custom properties without firing an event.",in:g("user login",{timestamp:1700000103,user:{id:"us3r",email:"user@acme.com"},data:{firstName:"Jane",lastName:"Doe",company:"Acme Corp",plan:"premium"}}),mapping:{silent:!0,settings:{identify:{map:{firstName:"data.firstName",lastName:"data.lastName",organization:"data.company",properties:{map:{plan:"data.plan"}}}}}},out:[["profilesApi.createOrUpdateProfile",{data:{type:"profile",attributes:{email:"user@acme.com",externalId:"us3r",firstName:"Jane",lastName:"Doe",organization:"Acme Corp",properties:{plan:"premium"}}}}]]},I={title:"Destination identify",description:"Destination-level identify upserts the Klaviyo profile with a first name before each event is sent.",in:g("page view",{timestamp:1700000104,user:{id:"us3r",email:"user@example.com",firstName:"Jane"}}),settings:{identify:{map:{firstName:"user.firstName"}}},out:[["profilesApi.createOrUpdateProfile",{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r",firstName:"Jane"}}}],["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"user@example.com",externalId:"us3r"}}},metric:{data:{type:"metric",attributes:{name:"page view"}}},properties:{},time:new Date(1700000104).toISOString()}}}]]},O={title:"Email only",description:"A newsletter signup uses only the email address as the Klaviyo profile identifier, with no external id.",in:g("newsletter signup",{timestamp:1700000105,user:{email:"subscriber@example.com"}}),settings:{externalId:void 0},out:[["eventsApi.createEvent",{data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{email:"subscriber@example.com"}}},metric:{data:{type:"metric",attributes:{name:"newsletter signup"}}},properties:{},time:new Date(1700000105).toISOString()}}}]]},P={public:!1,in:g("debug noise",{timestamp:1700000106,user:{id:"us3r",email:"user@example.com"}}),mapping:{ignore:!0},out:[]};export{m as examples,a as schemas};//# sourceMappingURL=dev.mjs.map
package/dist/dev.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n apiKey: z\n .string()\n .min(1)\n .describe(\n 'Klaviyo private API key. Starts with pk_. Find it under Settings > API Keys in your Klaviyo account.',\n ),\n email: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve email from each event (like user.email).',\n )\n .optional(),\n phoneNumber: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve phone number in E.164 format from each event.',\n )\n .optional(),\n externalId: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve external ID from each event (like user.id).',\n )\n .optional(),\n identify: z\n .unknown()\n .describe(\n 'Destination-level identity mapping. Resolves to profile attributes { firstName?, lastName?, organization?, properties? }. Fires createOrUpdateProfile() on first push and re-fires when values change.',\n )\n .optional(),\n currency: z\n .string()\n .length(3)\n .describe(\n 'Default ISO 4217 currency code for revenue events (like USD, EUR). Sets valueCurrency on Klaviyo events.',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z.object({\n identify: z\n .unknown()\n .describe(\n 'Per-event identify mapping. Resolves to profile attributes for createOrUpdateProfile(). Use with rule-level skip: true on login/signup events.',\n )\n .optional(),\n value: z\n .unknown()\n .describe(\n 'Revenue value mapping. Resolves to a numeric value for Klaviyo revenue tracking. Sets the value property and valueCurrency on the event.',\n )\n .optional(),\n});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type {\n Env,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from '../types';\n\nconst asyncNoop = () => Promise.resolve({});\n\nfunction createMockEventsApi(): KlaviyoEventsApiMock {\n return {\n createEvent: asyncNoop,\n };\n}\n\nfunction createMockProfilesApi(): KlaviyoProfilesApiMock {\n return {\n createOrUpdateProfile: asyncNoop,\n };\n}\n\nexport const push: Env = {\n eventsApi: createMockEventsApi(),\n profilesApi: createMockProfilesApi(),\n};\n\nexport const simulation = [\n 'call:eventsApi.createEvent',\n 'call:profilesApi.createOrUpdateProfile',\n];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Settings } from '../types';\n\n/**\n * Klaviyo SDK step examples.\n *\n * At push time, the destination invokes the `klaviyo-api` SDK. The public\n * method paths users see on the client are:\n *\n * - `eventsApi.createEvent(body)` — fires a metric event with inline profile\n * - `profilesApi.createOrUpdateProfile(body)` — upserts a profile\n *\n * Each `out` is therefore `[['method.path', ...args], ...]` matching the\n * actual SDK call order. `identify` fires before the event. When the rule\n * uses `skip: true` or `ignore: true`, `out` is `[]` or the identify-only\n * list.\n */\n\n/**\n * Extended step example that may carry destination-level settings overrides.\n */\nexport type KlaviyoStepExample = Flow.StepExample & {\n settings?: Partial<Settings>;\n};\n\n/**\n * Default event forwarding -- eventsApi.createEvent() with event name and\n * inline profile. Email resolved from default settings.email = 'user.email'.\n */\nexport const defaultEvent: KlaviyoStepExample = {\n title: 'Default event',\n description:\n 'An event is sent to Klaviyo as a metric with an inline profile resolved from the user email and id.',\n in: getEvent('product view', {\n timestamp: 1700000100,\n user: { id: 'us3r', email: 'user@example.com' },\n }),\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'product view' },\n },\n },\n properties: {},\n time: new Date(1700000100).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Mapped event name -- mapping.name renames the event to Klaviyo's expected\n * metric name for ecommerce reporting.\n */\nexport const mappedEventName: KlaviyoStepExample = {\n title: 'Viewed product',\n description:\n 'A product view is mapped to the Klaviyo Viewed Product metric with properties such as product name and price.',\n in: getEvent('product view', {\n timestamp: 1700000101,\n user: { id: 'us3r', email: 'user@example.com' },\n data: {\n name: 'USB Cable',\n id: 'PROD-1',\n price: 9.99,\n },\n }),\n mapping: {\n name: 'Viewed Product',\n data: {\n map: {\n ProductName: 'data.name',\n ProductID: 'data.id',\n Price: 'data.price',\n },\n },\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'Viewed Product' },\n },\n },\n properties: {\n ProductName: 'USB Cable',\n ProductID: 'PROD-1',\n Price: 9.99,\n },\n time: new Date(1700000101).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Revenue event -- order complete with value mapping. Sets $value and\n * valueCurrency on the Klaviyo event for revenue tracking.\n */\nexport const revenueEvent: KlaviyoStepExample = {\n title: 'Placed order',\n description:\n 'An order complete is sent to Klaviyo as Placed Order with value and currency for revenue attribution.',\n in: getEvent('order complete', {\n timestamp: 1700000102,\n user: { id: 'us3r', email: 'user@example.com' },\n data: {\n id: 'ORD-123',\n total: 99.99,\n itemNames: ['Widget A', 'Widget B'],\n },\n }),\n settings: {\n currency: 'EUR',\n },\n mapping: {\n name: 'Placed Order',\n data: {\n map: {\n OrderId: 'data.id',\n value: 'data.total',\n ItemNames: 'data.itemNames',\n },\n },\n settings: {\n value: 'data.total',\n },\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'Placed Order' },\n },\n },\n properties: {\n OrderId: 'ORD-123',\n value: 99.99,\n ItemNames: ['Widget A', 'Widget B'],\n },\n time: new Date(1700000102).toISOString(),\n valueCurrency: 'EUR',\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Per-event identify with skip -- user login fires\n * profilesApi.createOrUpdateProfile() only, no event tracked.\n */\nexport const userLoginIdentify: KlaviyoStepExample = {\n title: 'User login identify',\n description:\n 'A user login upserts the Klaviyo profile with name, organization, and custom properties without firing an event.',\n in: getEvent('user login', {\n timestamp: 1700000103,\n user: { id: 'us3r', email: 'user@acme.com' },\n data: {\n firstName: 'Jane',\n lastName: 'Doe',\n company: 'Acme Corp',\n plan: 'premium',\n },\n }),\n mapping: {\n skip: true,\n settings: {\n identify: {\n map: {\n firstName: 'data.firstName',\n lastName: 'data.lastName',\n organization: 'data.company',\n properties: {\n map: {\n plan: 'data.plan',\n },\n },\n },\n },\n },\n },\n out: [\n [\n 'profilesApi.createOrUpdateProfile',\n {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@acme.com',\n externalId: 'us3r',\n firstName: 'Jane',\n lastName: 'Doe',\n organization: 'Acme Corp',\n properties: {\n plan: 'premium',\n },\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Destination-level identify -- fires profilesApi.createOrUpdateProfile()\n * on first push when settings.identify resolves, then fires createEvent().\n */\nexport const destinationIdentify: KlaviyoStepExample = {\n title: 'Destination identify',\n description:\n 'Destination-level identify upserts the Klaviyo profile with a first name before each event is sent.',\n in: getEvent('page view', {\n timestamp: 1700000104,\n user: { id: 'us3r', email: 'user@example.com', firstName: 'Jane' },\n }),\n settings: {\n identify: {\n map: {\n firstName: 'user.firstName',\n },\n },\n },\n out: [\n [\n 'profilesApi.createOrUpdateProfile',\n {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n firstName: 'Jane',\n },\n },\n },\n ],\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'page view' },\n },\n },\n properties: {},\n time: new Date(1700000104).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Email only -- no externalId. Klaviyo accepts email as sole identifier.\n */\nexport const emailOnly: KlaviyoStepExample = {\n title: 'Email only',\n description:\n 'A newsletter signup uses only the email address as the Klaviyo profile identifier, with no external id.',\n in: getEvent('newsletter signup', {\n timestamp: 1700000105,\n user: { email: 'subscriber@example.com' },\n }),\n settings: {\n externalId: undefined,\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'subscriber@example.com',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'newsletter signup' },\n },\n },\n properties: {},\n time: new Date(1700000105).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Wildcard ignore -- the event matches a mapping rule with ignore: true.\n * The destination fires zero API calls.\n */\nexport const wildcardIgnored: KlaviyoStepExample = {\n public: false,\n in: getEvent('debug noise', {\n timestamp: 1700000106,\n user: { id: 'us3r', email: 'user@example.com' },\n }),\n mapping: { ignore: true },\n out: [],\n};\n"],"mappings":"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","names":["z"]}
1
+ {"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n apiKey: z\n .string()\n .min(1)\n .describe(\n 'Klaviyo private API key. Starts with pk_. Find it under Settings > API Keys in your Klaviyo account.',\n ),\n email: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve email from each event (like user.email).',\n )\n .optional(),\n phoneNumber: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve phone number in E.164 format from each event.',\n )\n .optional(),\n externalId: z\n .string()\n .describe(\n 'walkerOS mapping value path to resolve external ID from each event (like user.id).',\n )\n .optional(),\n identify: z\n .unknown()\n .describe(\n 'Destination-level identity mapping. Resolves to profile attributes { firstName?, lastName?, organization?, properties? }. Fires createOrUpdateProfile() on first push and re-fires when values change.',\n )\n .optional(),\n currency: z\n .string()\n .length(3)\n .describe(\n 'Default ISO 4217 currency code for revenue events (like USD, EUR). Sets valueCurrency on Klaviyo events.',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z.object({\n identify: z\n .unknown()\n .describe(\n 'Per-event identify mapping. Resolves to profile attributes for createOrUpdateProfile(). Use with rule-level silent: true on login/signup events.',\n )\n .optional(),\n value: z\n .unknown()\n .describe(\n 'Revenue value mapping. Resolves to a numeric value for Klaviyo revenue tracking. Sets the value property and valueCurrency on the event.',\n )\n .optional(),\n});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type {\n Env,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from '../types';\n\nconst asyncNoop = () => Promise.resolve({});\n\nfunction createMockEventsApi(): KlaviyoEventsApiMock {\n return {\n createEvent: asyncNoop,\n };\n}\n\nfunction createMockProfilesApi(): KlaviyoProfilesApiMock {\n return {\n createOrUpdateProfile: asyncNoop,\n };\n}\n\nexport const push: Env = {\n eventsApi: createMockEventsApi(),\n profilesApi: createMockProfilesApi(),\n};\n\nexport const simulation = [\n 'call:eventsApi.createEvent',\n 'call:profilesApi.createOrUpdateProfile',\n];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Settings } from '../types';\n\n/**\n * Klaviyo SDK step examples.\n *\n * At push time, the destination invokes the `klaviyo-api` SDK. The public\n * method paths users see on the client are:\n *\n * - `eventsApi.createEvent(body)` - fires a metric event with inline profile\n * - `profilesApi.createOrUpdateProfile(body)` - upserts a profile\n *\n * Each `out` is therefore `[['method.path', ...args], ...]` matching the\n * actual SDK call order. `identify` fires before the event. When the rule\n * uses `silent: true` or `ignore: true`, `out` is `[]` or the identify-only\n * list.\n */\n\n/**\n * Extended step example that may carry destination-level settings overrides.\n */\nexport type KlaviyoStepExample = Flow.StepExample & {\n settings?: Partial<Settings>;\n};\n\n/**\n * Default event forwarding -- eventsApi.createEvent() with event name and\n * inline profile. Email resolved from default settings.email = 'user.email'.\n */\nexport const defaultEvent: KlaviyoStepExample = {\n title: 'Default event',\n description:\n 'An event is sent to Klaviyo as a metric with an inline profile resolved from the user email and id.',\n in: getEvent('product view', {\n timestamp: 1700000100,\n user: { id: 'us3r', email: 'user@example.com' },\n }),\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'product view' },\n },\n },\n properties: {},\n time: new Date(1700000100).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Mapped event name -- mapping.name renames the event to Klaviyo's expected\n * metric name for ecommerce reporting.\n */\nexport const mappedEventName: KlaviyoStepExample = {\n title: 'Viewed product',\n description:\n 'A product view is mapped to the Klaviyo Viewed Product metric with properties such as product name and price.',\n in: getEvent('product view', {\n timestamp: 1700000101,\n user: { id: 'us3r', email: 'user@example.com' },\n data: {\n name: 'USB Cable',\n id: 'PROD-1',\n price: 9.99,\n },\n }),\n mapping: {\n name: 'Viewed Product',\n data: {\n map: {\n ProductName: 'data.name',\n ProductID: 'data.id',\n Price: 'data.price',\n },\n },\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'Viewed Product' },\n },\n },\n properties: {\n ProductName: 'USB Cable',\n ProductID: 'PROD-1',\n Price: 9.99,\n },\n time: new Date(1700000101).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Revenue event -- order complete with value mapping. Sets $value and\n * valueCurrency on the Klaviyo event for revenue tracking.\n */\nexport const revenueEvent: KlaviyoStepExample = {\n title: 'Placed order',\n description:\n 'An order complete is sent to Klaviyo as Placed Order with value and currency for revenue attribution.',\n in: getEvent('order complete', {\n timestamp: 1700000102,\n user: { id: 'us3r', email: 'user@example.com' },\n data: {\n id: 'ORD-123',\n total: 99.99,\n itemNames: ['Widget A', 'Widget B'],\n },\n }),\n settings: {\n currency: 'EUR',\n },\n mapping: {\n name: 'Placed Order',\n data: {\n map: {\n OrderId: 'data.id',\n value: 'data.total',\n ItemNames: 'data.itemNames',\n },\n },\n settings: {\n value: 'data.total',\n },\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'Placed Order' },\n },\n },\n properties: {\n OrderId: 'ORD-123',\n value: 99.99,\n ItemNames: ['Widget A', 'Widget B'],\n },\n time: new Date(1700000102).toISOString(),\n valueCurrency: 'EUR',\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Per-event identify with silent -- user login fires\n * profilesApi.createOrUpdateProfile() only, no event tracked.\n */\nexport const userLoginIdentify: KlaviyoStepExample = {\n title: 'User login identify',\n description:\n 'A user login upserts the Klaviyo profile with name, organization, and custom properties without firing an event.',\n in: getEvent('user login', {\n timestamp: 1700000103,\n user: { id: 'us3r', email: 'user@acme.com' },\n data: {\n firstName: 'Jane',\n lastName: 'Doe',\n company: 'Acme Corp',\n plan: 'premium',\n },\n }),\n mapping: {\n silent: true,\n settings: {\n identify: {\n map: {\n firstName: 'data.firstName',\n lastName: 'data.lastName',\n organization: 'data.company',\n properties: {\n map: {\n plan: 'data.plan',\n },\n },\n },\n },\n },\n },\n out: [\n [\n 'profilesApi.createOrUpdateProfile',\n {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@acme.com',\n externalId: 'us3r',\n firstName: 'Jane',\n lastName: 'Doe',\n organization: 'Acme Corp',\n properties: {\n plan: 'premium',\n },\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Destination-level identify -- fires profilesApi.createOrUpdateProfile()\n * on first push when settings.identify resolves, then fires createEvent().\n */\nexport const destinationIdentify: KlaviyoStepExample = {\n title: 'Destination identify',\n description:\n 'Destination-level identify upserts the Klaviyo profile with a first name before each event is sent.',\n in: getEvent('page view', {\n timestamp: 1700000104,\n user: { id: 'us3r', email: 'user@example.com', firstName: 'Jane' },\n }),\n settings: {\n identify: {\n map: {\n firstName: 'user.firstName',\n },\n },\n },\n out: [\n [\n 'profilesApi.createOrUpdateProfile',\n {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n firstName: 'Jane',\n },\n },\n },\n ],\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'user@example.com',\n externalId: 'us3r',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'page view' },\n },\n },\n properties: {},\n time: new Date(1700000104).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Email only -- no externalId. Klaviyo accepts email as sole identifier.\n */\nexport const emailOnly: KlaviyoStepExample = {\n title: 'Email only',\n description:\n 'A newsletter signup uses only the email address as the Klaviyo profile identifier, with no external id.',\n in: getEvent('newsletter signup', {\n timestamp: 1700000105,\n user: { email: 'subscriber@example.com' },\n }),\n settings: {\n externalId: undefined,\n },\n out: [\n [\n 'eventsApi.createEvent',\n {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: {\n email: 'subscriber@example.com',\n },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: 'newsletter signup' },\n },\n },\n properties: {},\n time: new Date(1700000105).toISOString(),\n },\n },\n },\n ],\n ],\n};\n\n/**\n * Wildcard ignore -- the event matches a mapping rule with ignore: true.\n * The destination fires zero API calls.\n */\nexport const wildcardIgnored: KlaviyoStepExample = {\n public: false,\n in: getEvent('debug noise', {\n timestamp: 1700000106,\n user: { id: 'us3r', email: 'user@example.com' },\n }),\n mapping: { ignore: true },\n out: [],\n};\n"],"mappings":"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","names":["z"]}
@@ -64,12 +64,12 @@ declare namespace env {
64
64
  * At push time, the destination invokes the `klaviyo-api` SDK. The public
65
65
  * method paths users see on the client are:
66
66
  *
67
- * - `eventsApi.createEvent(body)` fires a metric event with inline profile
68
- * - `profilesApi.createOrUpdateProfile(body)` upserts a profile
67
+ * - `eventsApi.createEvent(body)` - fires a metric event with inline profile
68
+ * - `profilesApi.createOrUpdateProfile(body)` - upserts a profile
69
69
  *
70
70
  * Each `out` is therefore `[['method.path', ...args], ...]` matching the
71
71
  * actual SDK call order. `identify` fires before the event. When the rule
72
- * uses `skip: true` or `ignore: true`, `out` is `[]` or the identify-only
72
+ * uses `silent: true` or `ignore: true`, `out` is `[]` or the identify-only
73
73
  * list.
74
74
  */
75
75
  /**
@@ -94,7 +94,7 @@ declare const mappedEventName: KlaviyoStepExample;
94
94
  */
95
95
  declare const revenueEvent: KlaviyoStepExample;
96
96
  /**
97
- * Per-event identify with skip -- user login fires
97
+ * Per-event identify with silent -- user login fires
98
98
  * profilesApi.createOrUpdateProfile() only, no event tracked.
99
99
  */
100
100
  declare const userLoginIdentify: KlaviyoStepExample;
@@ -64,12 +64,12 @@ declare namespace env {
64
64
  * At push time, the destination invokes the `klaviyo-api` SDK. The public
65
65
  * method paths users see on the client are:
66
66
  *
67
- * - `eventsApi.createEvent(body)` fires a metric event with inline profile
68
- * - `profilesApi.createOrUpdateProfile(body)` upserts a profile
67
+ * - `eventsApi.createEvent(body)` - fires a metric event with inline profile
68
+ * - `profilesApi.createOrUpdateProfile(body)` - upserts a profile
69
69
  *
70
70
  * Each `out` is therefore `[['method.path', ...args], ...]` matching the
71
71
  * actual SDK call order. `identify` fires before the event. When the rule
72
- * uses `skip: true` or `ignore: true`, `out` is `[]` or the identify-only
72
+ * uses `silent: true` or `ignore: true`, `out` is `[]` or the identify-only
73
73
  * list.
74
74
  */
75
75
  /**
@@ -94,7 +94,7 @@ declare const mappedEventName: KlaviyoStepExample;
94
94
  */
95
95
  declare const revenueEvent: KlaviyoStepExample;
96
96
  /**
97
- * Per-event identify with skip -- user login fires
97
+ * Per-event identify with silent -- user login fires
98
98
  * profilesApi.createOrUpdateProfile() only, no event tracked.
99
99
  */
100
100
  declare const userLoginIdentify: KlaviyoStepExample;
@@ -233,7 +233,7 @@ var userLoginIdentify = {
233
233
  }
234
234
  }),
235
235
  mapping: {
236
- skip: true,
236
+ silent: true,
237
237
  settings: {
238
238
  identify: {
239
239
  map: {
@@ -212,7 +212,7 @@ var userLoginIdentify = {
212
212
  }
213
213
  }),
214
214
  mapping: {
215
- skip: true,
215
+ silent: true,
216
216
  settings: {
217
217
  identify: {
218
218
  map: {
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e,t=Object.defineProperty,i=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,r=Object.prototype.hasOwnProperty,a={};((e,i)=>{for(var n in i)t(e,n,{get:i[n],enumerable:!0})})(a,{DestinationKlaviyo:()=>p,default:()=>c,destinationKlaviyo:()=>u}),module.exports=(e=a,((e,a,o,l)=>{if(a&&"object"==typeof a||"function"==typeof a)for(let s of n(a))r.call(e,s)||s===o||t(e,s,{get:()=>a[s],enumerable:!(l=i(a,s))||l.enumerable});return e})(t({},"__esModule",{value:!0}),e));var o=require("@walkeros/core"),l=async function(e,{config:t,rule:i,data:n,collector:r,env:a,logger:l}){var p;const u=t.settings,c=a,f=(null==c?void 0:c.eventsApi)||u._eventsApi,v=(null==c?void 0:c.profilesApi)||u._profilesApi;if(!f||!v)return void l.warn("Klaviyo API instances not initialized");const d=u._state||{},y=(null==i?void 0:i.settings)||{},g=new Date(e.timestamp||Date.now()),m=u.email?s(await(0,o.getMappingValue)(e,u.email,{collector:r})):void 0,b=u.externalId?s(await(0,o.getMappingValue)(e,u.externalId,{collector:r})):void 0,w=u.phoneNumber?s(await(0,o.getMappingValue)(e,u.phoneNumber,{collector:r})):void 0;if(!m&&!b&&!w)return void l.warn("Klaviyo requires at least one profile identifier; skipping event",{event:e.name});const h={};m&&(h.email=m),b&&(h.externalId=b),w&&(h.phoneNumber=w);const N=null!=(p=y.identify)?p:u.identify;if(void 0!==N){const t=await(0,o.getMappingValue)(e,N,{collector:r});(0,o.isObject)(t)&&await async function(e,t,i,n){var r;const a=n.lastIdentity||{},l=function(e){if(!e)return"";try{return JSON.stringify(e)}catch(e){return""}}(t),s=i.email!==a.email||i.externalId!==a.externalId||i.phoneNumber!==a.phoneNumber,p=l!==(null!=(r=a.traitsHash)?r:"");if(!s&&!p)return;const u={...i},c=["firstName","lastName","organization","title","image","location"];for(const e of c)void 0!==t[e]&&(u[e]=t[e]);(0,o.isObject)(t.properties)&&!(0,o.isArray)(t.properties)&&(u.properties=t.properties);const f={data:{type:"profile",attributes:u}};await e.createOrUpdateProfile(f),n.lastIdentity={email:i.email,externalId:i.externalId,phoneNumber:i.phoneNumber,traitsHash:l}}(v,t,h,d)}if(!0!==(null==i?void 0:i.skip)){const t=(0,o.isString)(null==i?void 0:i.name)?i.name:e.name,a=(0,o.isObject)(n)?{...n}:{};let l;if(void 0!==y.value){const t=function(e){if("number"==typeof e&&!isNaN(e))return e;if((0,o.isString)(e)){const t=parseFloat(e);if(!isNaN(t))return t}return}(await(0,o.getMappingValue)(e,y.value,{collector:r}));void 0!==t&&(a.value=t,u.currency&&(l=u.currency))}const s={data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{...h}}},metric:{data:{type:"metric",attributes:{name:t}}},properties:a,time:g.toISOString(),...l?{valueCurrency:l}:{}}}};await f.createEvent(s)}u._state=d};function s(e){if((0,o.isString)(e)&&e.length>0)return e}var p={},u={type:"klaviyo",config:{},init({config:e,logger:t,env:i}){const n=function(e={},t){var i,n;const r=e.settings||{},{apiKey:a}=r;a||t.throw("Config settings apiKey missing");const o={...r,apiKey:a,email:null!=(i=r.email)?i:"user.email",externalId:null!=(n=r.externalId)?n:"user.id"};return{...e,settings:o}}(e,t),r=n.settings,a=i;if(!(null==a?void 0:a.eventsApi)||!(null==a?void 0:a.profilesApi))try{const e=require("klaviyo-api"),{ApiKeySession:t,EventsApi:i,ProfilesApi:n}=e,a=new t(r.apiKey);r._eventsApi=new i(a),r._profilesApi=new n(a)}catch(e){t.throw(`Failed to initialize Klaviyo SDK: ${e}`)}return r._state={},n},push:async(e,t)=>await l(e,t)},c=u;//# sourceMappingURL=index.js.map
1
+ "use strict";var e,t=Object.defineProperty,i=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,r=Object.prototype.hasOwnProperty,a={};((e,i)=>{for(var n in i)t(e,n,{get:i[n],enumerable:!0})})(a,{DestinationKlaviyo:()=>p,default:()=>u,destinationKlaviyo:()=>c}),module.exports=(e=a,((e,a,o,s)=>{if(a&&"object"==typeof a||"function"==typeof a)for(let l of n(a))r.call(e,l)||l===o||t(e,l,{get:()=>a[l],enumerable:!(s=i(a,l))||s.enumerable});return e})(t({},"__esModule",{value:!0}),e));var o=require("@walkeros/core"),s=async function(e,{config:t,rule:i,data:n,collector:r,env:a,logger:s}){const p=t.settings,c=a,u=c?.eventsApi||p._eventsApi,f=c?.profilesApi||p._profilesApi;if(!u||!f)return void s.warn("Klaviyo API instances not initialized");const y=p._state||{},g=i?.settings||{},d=new Date(e.timestamp||Date.now()),m=p.email?l(await(0,o.getMappingValue)(e,p.email,{collector:r})):void 0,v=p.externalId?l(await(0,o.getMappingValue)(e,p.externalId,{collector:r})):void 0,b=p.phoneNumber?l(await(0,o.getMappingValue)(e,p.phoneNumber,{collector:r})):void 0;if(!m&&!v&&!b)return void s.warn("Klaviyo requires at least one profile identifier; skipping event",{event:e.name});const w={};m&&(w.email=m),v&&(w.externalId=v),b&&(w.phoneNumber=b);const h=g.identify??p.identify;if(void 0!==h){const t=await(0,o.getMappingValue)(e,h,{collector:r});(0,o.isObject)(t)&&await async function(e,t,i,n){const r=n.lastIdentity||{},a=function(e){if(!e)return"";try{return JSON.stringify(e)}catch{return""}}(t),s=i.email!==r.email||i.externalId!==r.externalId||i.phoneNumber!==r.phoneNumber,l=a!==(r.traitsHash??"");if(!s&&!l)return;const p={...i},c=["firstName","lastName","organization","title","image","location"];for(const e of c)void 0!==t[e]&&(p[e]=t[e]);(0,o.isObject)(t.properties)&&!(0,o.isArray)(t.properties)&&(p.properties=t.properties);const u={data:{type:"profile",attributes:p}};await e.createOrUpdateProfile(u),n.lastIdentity={email:i.email,externalId:i.externalId,phoneNumber:i.phoneNumber,traitsHash:a}}(f,t,w,y)}if(!0!==i?.silent){const t=(0,o.isString)(i?.name)?i.name:e.name,a=(0,o.isObject)(n)?{...n}:{};let s;if(void 0!==g.value){const t=function(e){if("number"==typeof e&&!isNaN(e))return e;if((0,o.isString)(e)){const t=parseFloat(e);if(!isNaN(t))return t}return}(await(0,o.getMappingValue)(e,g.value,{collector:r}));void 0!==t&&(a.value=t,p.currency&&(s=p.currency))}const l={data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{...w}}},metric:{data:{type:"metric",attributes:{name:t}}},properties:a,time:d.toISOString(),...s?{valueCurrency:s}:{}}}};await u.createEvent(l)}p._state=y};function l(e){if((0,o.isString)(e)&&e.length>0)return e}var p={},c={type:"klaviyo",config:{},init({config:e,logger:t,env:i}){const n=function(e={},t){const i=e.settings||{},{apiKey:n}=i;n||t.throw("Config settings apiKey missing");const r={...i,apiKey:n,email:i.email??"user.email",externalId:i.externalId??"user.id"};return{...e,settings:r}}(e,t),r=n.settings,a=i;if(!a?.eventsApi||!a?.profilesApi)try{const e=require("klaviyo-api"),{ApiKeySession:t,EventsApi:i,ProfilesApi:n}=e,a=new t(r.apiKey);r._eventsApi=new i(a),r._profilesApi=new n(a)}catch(e){t.throw(`Failed to initialize Klaviyo SDK: ${e}`)}return r._state={},n},push:async(e,t)=>await s(e,t)},u=c;//# 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/types/index.ts"],"sourcesContent":["import type {\n Destination,\n Settings,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationKlaviyo from './types';\n\nexport const destinationKlaviyo: Destination = {\n type: 'klaviyo',\n\n config: {},\n\n init({ config: partialConfig, logger, env }) {\n const config = getConfig(partialConfig, logger);\n const settings = config.settings as Settings;\n\n // Use env mocks if provided (testing), otherwise create real SDK instances\n const envTyped = env as\n | {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n }\n | undefined;\n\n if (!envTyped?.eventsApi || !envTyped?.profilesApi) {\n // Production path: create real API instances\n try {\n // Use dynamic require to avoid bundling the SDK when not needed\n // and to allow tests to mock via jest.mock('klaviyo-api').\n const klaviyoApi = require('klaviyo-api');\n const { ApiKeySession, EventsApi, ProfilesApi } = klaviyoApi;\n const session = new ApiKeySession(settings.apiKey);\n settings._eventsApi = new EventsApi(session) as KlaviyoEventsApiMock;\n settings._profilesApi = new ProfilesApi(\n session,\n ) as KlaviyoProfilesApiMock;\n } catch (err) {\n logger.throw(`Failed to initialize Klaviyo SDK: ${err}`);\n }\n }\n\n settings._state = {};\n\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationKlaviyo;\n","import type { Config, Settings, PartialConfig } 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 } = settings;\n\n if (!apiKey) logger.throw('Config settings apiKey missing');\n\n const settingsConfig: Settings = {\n ...settings,\n apiKey,\n // Default identity resolution paths\n email: settings.email ?? 'user.email',\n externalId: settings.externalId ?? 'user.id',\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n PushFn,\n Settings,\n RuntimeState,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from './types';\nimport { getMappingValue, isObject, isString, isArray } from '@walkeros/core';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, collector, env, logger },\n) {\n const settings = config.settings as Settings;\n\n // Resolve SDK instances: prefer env mocks (testing), fall back to real\n const envTyped = env as\n | {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n }\n | undefined;\n const eventsApi = envTyped?.eventsApi || settings._eventsApi;\n const profilesApi = envTyped?.profilesApi || settings._profilesApi;\n\n if (!eventsApi || !profilesApi) {\n logger.warn('Klaviyo API instances not initialized');\n return;\n }\n\n const state: RuntimeState = settings._state || {};\n const mappingSettings = rule?.settings || {};\n const timestamp = new Date(event.timestamp || Date.now());\n\n // 1. Resolve identity from event\n const email = settings.email\n ? resolveString(await getMappingValue(event, settings.email, { collector }))\n : undefined;\n const externalId = settings.externalId\n ? resolveString(\n await getMappingValue(event, settings.externalId, { collector }),\n )\n : undefined;\n const phoneNumber = settings.phoneNumber\n ? resolveString(\n await getMappingValue(event, settings.phoneNumber, { collector }),\n )\n : undefined;\n\n if (!email && !externalId && !phoneNumber) {\n logger.warn(\n 'Klaviyo requires at least one profile identifier; skipping event',\n { event: event.name },\n );\n return;\n }\n\n // Build profile identifier object\n const profileIdentifiers: Record<string, string> = {};\n if (email) profileIdentifiers.email = email;\n if (externalId) profileIdentifiers.externalId = externalId;\n if (phoneNumber) profileIdentifiers.phoneNumber = phoneNumber;\n\n // 2. Identify -- rule-level overrides destination-level\n const identifyMapping = mappingSettings.identify ?? settings.identify;\n if (identifyMapping !== undefined) {\n const resolved = await getMappingValue(event, identifyMapping, {\n collector,\n });\n if (isObject(resolved)) {\n await applyIdentify(\n profilesApi,\n resolved as Record<string, unknown>,\n profileIdentifiers,\n state,\n );\n }\n }\n\n // 3. Track event (unless skip: true)\n if (rule?.skip !== true) {\n const eventName = isString(rule?.name) ? rule.name : event.name;\n const properties = isObject(data)\n ? { ...(data as Record<string, unknown>) }\n : {};\n\n // Handle revenue value\n let valueCurrency: string | undefined;\n if (mappingSettings.value !== undefined) {\n const resolvedValue = await getMappingValue(\n event,\n mappingSettings.value,\n {\n collector,\n },\n );\n const numericValue = toNumber(resolvedValue);\n if (numericValue !== undefined) {\n properties.value = numericValue;\n if (settings.currency) {\n valueCurrency = settings.currency;\n }\n }\n }\n\n const eventBody: Record<string, unknown> = {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: { ...profileIdentifiers },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: eventName },\n },\n },\n properties,\n time: timestamp.toISOString(),\n ...(valueCurrency ? { valueCurrency } : {}),\n },\n },\n };\n\n await eventsApi.createEvent(eventBody);\n }\n\n settings._state = state;\n};\n\nfunction resolveString(value: unknown): string | undefined {\n if (isString(value) && value.length > 0) return value;\n return undefined;\n}\n\nfunction toNumber(value: unknown): number | undefined {\n if (typeof value === 'number' && !isNaN(value)) return value;\n if (isString(value)) {\n const parsed = parseFloat(value);\n if (!isNaN(parsed)) return parsed;\n }\n return undefined;\n}\n\nfunction hashTraits(traits: Record<string, unknown> | undefined): string {\n if (!traits) return '';\n try {\n return JSON.stringify(traits);\n } catch {\n return '';\n }\n}\n\nasync function applyIdentify(\n profilesApi: KlaviyoProfilesApiMock,\n resolved: Record<string, unknown>,\n profileIdentifiers: Record<string, string>,\n state: RuntimeState,\n): Promise<void> {\n const last = state.lastIdentity || {};\n\n // Build traits hash from resolved attributes for dedup\n const traitsHash = hashTraits(resolved);\n const identityChanged =\n profileIdentifiers.email !== last.email ||\n profileIdentifiers.externalId !== last.externalId ||\n profileIdentifiers.phoneNumber !== last.phoneNumber;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n\n if (!identityChanged && !traitsChanged) return;\n\n // Build profile attributes from resolved mapping\n const attributes: Record<string, unknown> = {\n ...profileIdentifiers,\n };\n\n // Standard Klaviyo profile attributes\n const standardAttrs = [\n 'firstName',\n 'lastName',\n 'organization',\n 'title',\n 'image',\n 'location',\n ];\n for (const attr of standardAttrs) {\n if (resolved[attr] !== undefined) {\n attributes[attr] = resolved[attr];\n }\n }\n\n // Custom properties\n if (isObject(resolved.properties) && !isArray(resolved.properties)) {\n attributes.properties = resolved.properties;\n }\n\n const body: Record<string, unknown> = {\n data: {\n type: 'profile',\n attributes,\n },\n };\n\n await profilesApi.createOrUpdateProfile(body);\n\n state.lastIdentity = {\n email: profileIdentifiers.email,\n externalId: profileIdentifiers.externalId,\n phoneNumber: profileIdentifiers.phoneNumber,\n traitsHash,\n };\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\n\nexport interface Settings {\n /** Klaviyo private API key (required). Starts with 'pk_'. */\n apiKey: string;\n /** walkerOS mapping value path to resolve email from each event. */\n email?: string;\n /** walkerOS mapping value path to resolve phone number (E.164) from each event. */\n phoneNumber?: string;\n /** walkerOS mapping value path to resolve external ID from each event. */\n externalId?: string;\n /** Destination-level identify mapping. Resolves to profile attributes for upsert. */\n identify?: WalkerOSMapping.Value;\n /** Default currency for revenue events (ISO 4217, e.g. 'USD', 'EUR'). */\n currency?: string;\n /** Runtime state -- not user-facing. Mutated by init/push. */\n _eventsApi?: KlaviyoEventsApiMock;\n _profilesApi?: KlaviyoProfilesApiMock;\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n lastIdentity?: {\n email?: string;\n externalId?: string;\n phoneNumber?: string;\n traitsHash?: string;\n };\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Resolved via getMappingValue() in push().\n */\nexport interface Mapping {\n /** Per-event identify mapping. Resolves to profile attributes for upsert. */\n identify?: WalkerOSMapping.Value;\n /** Revenue value mapping. Resolves to numeric value for Klaviyo's $value. */\n value?: WalkerOSMapping.Value;\n}\n\n/**\n * Env -- optional SDK override. Production leaves this undefined and the\n * destination creates real API instances. Tests provide mocks via\n * env.eventsApi and env.profilesApi.\n */\nexport interface Env extends DestinationServer.Env {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n}\n\n/**\n * Mock-friendly interface for EventsApi.createEvent().\n */\nexport interface KlaviyoEventsApiMock {\n createEvent: (body: Record<string, unknown>) => Promise<unknown>;\n}\n\n/**\n * Mock-friendly interface for ProfilesApi.createOrUpdateProfile().\n */\nexport interface KlaviyoProfilesApiMock {\n createOrUpdateProfile: (body: Record<string, unknown>) => Promise<unknown>;\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"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/types/index.ts"],"sourcesContent":["import type {\n Destination,\n Settings,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationKlaviyo from './types';\n\nexport const destinationKlaviyo: Destination = {\n type: 'klaviyo',\n\n config: {},\n\n init({ config: partialConfig, logger, env }) {\n const config = getConfig(partialConfig, logger);\n const settings = config.settings as Settings;\n\n // Use env mocks if provided (testing), otherwise create real SDK instances\n const envTyped = env as\n | {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n }\n | undefined;\n\n if (!envTyped?.eventsApi || !envTyped?.profilesApi) {\n // Production path: create real API instances\n try {\n // Use dynamic require to avoid bundling the SDK when not needed\n // and to allow tests to mock via jest.mock('klaviyo-api').\n const klaviyoApi = require('klaviyo-api');\n const { ApiKeySession, EventsApi, ProfilesApi } = klaviyoApi;\n const session = new ApiKeySession(settings.apiKey);\n settings._eventsApi = new EventsApi(session) as KlaviyoEventsApiMock;\n settings._profilesApi = new ProfilesApi(\n session,\n ) as KlaviyoProfilesApiMock;\n } catch (err) {\n logger.throw(`Failed to initialize Klaviyo SDK: ${err}`);\n }\n }\n\n settings._state = {};\n\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationKlaviyo;\n","import type { Config, Settings, PartialConfig } 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 } = settings;\n\n if (!apiKey) logger.throw('Config settings apiKey missing');\n\n const settingsConfig: Settings = {\n ...settings,\n apiKey,\n // Default identity resolution paths\n email: settings.email ?? 'user.email',\n externalId: settings.externalId ?? 'user.id',\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n PushFn,\n Settings,\n RuntimeState,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from './types';\nimport { getMappingValue, isObject, isString, isArray } from '@walkeros/core';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, collector, env, logger },\n) {\n const settings = config.settings as Settings;\n\n // Resolve SDK instances: prefer env mocks (testing), fall back to real\n const envTyped = env as\n | {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n }\n | undefined;\n const eventsApi = envTyped?.eventsApi || settings._eventsApi;\n const profilesApi = envTyped?.profilesApi || settings._profilesApi;\n\n if (!eventsApi || !profilesApi) {\n logger.warn('Klaviyo API instances not initialized');\n return;\n }\n\n const state: RuntimeState = settings._state || {};\n const mappingSettings = rule?.settings || {};\n const timestamp = new Date(event.timestamp || Date.now());\n\n // 1. Resolve identity from event\n const email = settings.email\n ? resolveString(await getMappingValue(event, settings.email, { collector }))\n : undefined;\n const externalId = settings.externalId\n ? resolveString(\n await getMappingValue(event, settings.externalId, { collector }),\n )\n : undefined;\n const phoneNumber = settings.phoneNumber\n ? resolveString(\n await getMappingValue(event, settings.phoneNumber, { collector }),\n )\n : undefined;\n\n if (!email && !externalId && !phoneNumber) {\n logger.warn(\n 'Klaviyo requires at least one profile identifier; skipping event',\n { event: event.name },\n );\n return;\n }\n\n // Build profile identifier object\n const profileIdentifiers: Record<string, string> = {};\n if (email) profileIdentifiers.email = email;\n if (externalId) profileIdentifiers.externalId = externalId;\n if (phoneNumber) profileIdentifiers.phoneNumber = phoneNumber;\n\n // 2. Identify -- rule-level overrides destination-level\n const identifyMapping = mappingSettings.identify ?? settings.identify;\n if (identifyMapping !== undefined) {\n const resolved = await getMappingValue(event, identifyMapping, {\n collector,\n });\n if (isObject(resolved)) {\n await applyIdentify(\n profilesApi,\n resolved as Record<string, unknown>,\n profileIdentifiers,\n state,\n );\n }\n }\n\n // 3. Track event (unless silent: true)\n if (rule?.silent !== true) {\n const eventName = isString(rule?.name) ? rule.name : event.name;\n const properties = isObject(data)\n ? { ...(data as Record<string, unknown>) }\n : {};\n\n // Handle revenue value\n let valueCurrency: string | undefined;\n if (mappingSettings.value !== undefined) {\n const resolvedValue = await getMappingValue(\n event,\n mappingSettings.value,\n {\n collector,\n },\n );\n const numericValue = toNumber(resolvedValue);\n if (numericValue !== undefined) {\n properties.value = numericValue;\n if (settings.currency) {\n valueCurrency = settings.currency;\n }\n }\n }\n\n const eventBody: Record<string, unknown> = {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: { ...profileIdentifiers },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: eventName },\n },\n },\n properties,\n time: timestamp.toISOString(),\n ...(valueCurrency ? { valueCurrency } : {}),\n },\n },\n };\n\n await eventsApi.createEvent(eventBody);\n }\n\n settings._state = state;\n};\n\nfunction resolveString(value: unknown): string | undefined {\n if (isString(value) && value.length > 0) return value;\n return undefined;\n}\n\nfunction toNumber(value: unknown): number | undefined {\n if (typeof value === 'number' && !isNaN(value)) return value;\n if (isString(value)) {\n const parsed = parseFloat(value);\n if (!isNaN(parsed)) return parsed;\n }\n return undefined;\n}\n\nfunction hashTraits(traits: Record<string, unknown> | undefined): string {\n if (!traits) return '';\n try {\n return JSON.stringify(traits);\n } catch {\n return '';\n }\n}\n\nasync function applyIdentify(\n profilesApi: KlaviyoProfilesApiMock,\n resolved: Record<string, unknown>,\n profileIdentifiers: Record<string, string>,\n state: RuntimeState,\n): Promise<void> {\n const last = state.lastIdentity || {};\n\n // Build traits hash from resolved attributes for dedup\n const traitsHash = hashTraits(resolved);\n const identityChanged =\n profileIdentifiers.email !== last.email ||\n profileIdentifiers.externalId !== last.externalId ||\n profileIdentifiers.phoneNumber !== last.phoneNumber;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n\n if (!identityChanged && !traitsChanged) return;\n\n // Build profile attributes from resolved mapping\n const attributes: Record<string, unknown> = {\n ...profileIdentifiers,\n };\n\n // Standard Klaviyo profile attributes\n const standardAttrs = [\n 'firstName',\n 'lastName',\n 'organization',\n 'title',\n 'image',\n 'location',\n ];\n for (const attr of standardAttrs) {\n if (resolved[attr] !== undefined) {\n attributes[attr] = resolved[attr];\n }\n }\n\n // Custom properties\n if (isObject(resolved.properties) && !isArray(resolved.properties)) {\n attributes.properties = resolved.properties;\n }\n\n const body: Record<string, unknown> = {\n data: {\n type: 'profile',\n attributes,\n },\n };\n\n await profilesApi.createOrUpdateProfile(body);\n\n state.lastIdentity = {\n email: profileIdentifiers.email,\n externalId: profileIdentifiers.externalId,\n phoneNumber: profileIdentifiers.phoneNumber,\n traitsHash,\n };\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\n\nexport interface Settings {\n /** Klaviyo private API key (required). Starts with 'pk_'. */\n apiKey: string;\n /** walkerOS mapping value path to resolve email from each event. */\n email?: string;\n /** walkerOS mapping value path to resolve phone number (E.164) from each event. */\n phoneNumber?: string;\n /** walkerOS mapping value path to resolve external ID from each event. */\n externalId?: string;\n /** Destination-level identify mapping. Resolves to profile attributes for upsert. */\n identify?: WalkerOSMapping.Value;\n /** Default currency for revenue events (ISO 4217, e.g. 'USD', 'EUR'). */\n currency?: string;\n /** Runtime state -- not user-facing. Mutated by init/push. */\n _eventsApi?: KlaviyoEventsApiMock;\n _profilesApi?: KlaviyoProfilesApiMock;\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n lastIdentity?: {\n email?: string;\n externalId?: string;\n phoneNumber?: string;\n traitsHash?: string;\n };\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Resolved via getMappingValue() in push().\n */\nexport interface Mapping {\n /** Per-event identify mapping. Resolves to profile attributes for upsert. */\n identify?: WalkerOSMapping.Value;\n /** Revenue value mapping. Resolves to numeric value for Klaviyo's $value. */\n value?: WalkerOSMapping.Value;\n}\n\n/**\n * Env -- optional SDK override. Production leaves this undefined and the\n * destination creates real API instances. Tests provide mocks via\n * env.eventsApi and env.profilesApi.\n */\nexport interface Env extends DestinationServer.Env {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n}\n\n/**\n * Mock-friendly interface for EventsApi.createEvent().\n */\nexport interface KlaviyoEventsApiMock {\n createEvent: (body: Record<string, unknown>) => Promise<unknown>;\n}\n\n/**\n * Mock-friendly interface for ProfilesApi.createOrUpdateProfile().\n */\nexport interface KlaviyoProfilesApiMock {\n createOrUpdateProfile: (body: Record<string, unknown>) => Promise<unknown>;\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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGO,SAAS,UACd,gBAA+B,CAAC,GAChC,QACQ;AACR,QAAM,WAAY,cAAc,YAAY,CAAC;AAC7C,QAAM,EAAE,OAAO,IAAI;AAEnB,MAAI,CAAC,OAAQ,QAAO,MAAM,gCAAgC;AAE1D,QAAM,iBAA2B;AAAA,IAC/B,GAAG;AAAA,IACH;AAAA;AAAA,IAEA,OAAO,SAAS,SAAS;AAAA,IACzB,YAAY,SAAS,cAAc;AAAA,EACrC;AAEA,SAAO,EAAE,GAAG,eAAe,UAAU,eAAe;AACtD;;;ACdA,kBAA6D;AAEtD,IAAM,OAAe,eAC1B,OACA,EAAE,QAAQ,MAAM,MAAM,WAAW,KAAK,OAAO,GAC7C;AACA,QAAM,WAAW,OAAO;AAGxB,QAAM,WAAW;AAMjB,QAAM,YAAY,UAAU,aAAa,SAAS;AAClD,QAAM,cAAc,UAAU,eAAe,SAAS;AAEtD,MAAI,CAAC,aAAa,CAAC,aAAa;AAC9B,WAAO,KAAK,uCAAuC;AACnD;AAAA,EACF;AAEA,QAAM,QAAsB,SAAS,UAAU,CAAC;AAChD,QAAM,kBAAkB,MAAM,YAAY,CAAC;AAC3C,QAAM,YAAY,IAAI,KAAK,MAAM,aAAa,KAAK,IAAI,CAAC;AAGxD,QAAM,QAAQ,SAAS,QACnB,cAAc,UAAM,6BAAgB,OAAO,SAAS,OAAO,EAAE,UAAU,CAAC,CAAC,IACzE;AACJ,QAAM,aAAa,SAAS,aACxB;AAAA,IACE,UAAM,6BAAgB,OAAO,SAAS,YAAY,EAAE,UAAU,CAAC;AAAA,EACjE,IACA;AACJ,QAAM,cAAc,SAAS,cACzB;AAAA,IACE,UAAM,6BAAgB,OAAO,SAAS,aAAa,EAAE,UAAU,CAAC;AAAA,EAClE,IACA;AAEJ,MAAI,CAAC,SAAS,CAAC,cAAc,CAAC,aAAa;AACzC,WAAO;AAAA,MACL;AAAA,MACA,EAAE,OAAO,MAAM,KAAK;AAAA,IACtB;AACA;AAAA,EACF;AAGA,QAAM,qBAA6C,CAAC;AACpD,MAAI,MAAO,oBAAmB,QAAQ;AACtC,MAAI,WAAY,oBAAmB,aAAa;AAChD,MAAI,YAAa,oBAAmB,cAAc;AAGlD,QAAM,kBAAkB,gBAAgB,YAAY,SAAS;AAC7D,MAAI,oBAAoB,QAAW;AACjC,UAAM,WAAW,UAAM,6BAAgB,OAAO,iBAAiB;AAAA,MAC7D;AAAA,IACF,CAAC;AACD,YAAI,sBAAS,QAAQ,GAAG;AACtB,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,MAAM,WAAW,MAAM;AACzB,UAAM,gBAAY,sBAAS,MAAM,IAAI,IAAI,KAAK,OAAO,MAAM;AAC3D,UAAM,iBAAa,sBAAS,IAAI,IAC5B,EAAE,GAAI,KAAiC,IACvC,CAAC;AAGL,QAAI;AACJ,QAAI,gBAAgB,UAAU,QAAW;AACvC,YAAM,gBAAgB,UAAM;AAAA,QAC1B;AAAA,QACA,gBAAgB;AAAA,QAChB;AAAA,UACE;AAAA,QACF;AAAA,MACF;AACA,YAAM,eAAe,SAAS,aAAa;AAC3C,UAAI,iBAAiB,QAAW;AAC9B,mBAAW,QAAQ;AACnB,YAAI,SAAS,UAAU;AACrB,0BAAgB,SAAS;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAqC;AAAA,MACzC,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS;AAAA,YACP,MAAM;AAAA,cACJ,MAAM;AAAA,cACN,YAAY,EAAE,GAAG,mBAAmB;AAAA,YACtC;AAAA,UACF;AAAA,UACA,QAAQ;AAAA,YACN,MAAM;AAAA,cACJ,MAAM;AAAA,cACN,YAAY,EAAE,MAAM,UAAU;AAAA,YAChC;AAAA,UACF;AAAA,UACA;AAAA,UACA,MAAM,UAAU,YAAY;AAAA,UAC5B,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,YAAY,SAAS;AAAA,EACvC;AAEA,WAAS,SAAS;AACpB;AAEA,SAAS,cAAc,OAAoC;AACzD,UAAI,sBAAS,KAAK,KAAK,MAAM,SAAS,EAAG,QAAO;AAChD,SAAO;AACT;AAEA,SAAS,SAAS,OAAoC;AACpD,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,EAAG,QAAO;AACvD,UAAI,sBAAS,KAAK,GAAG;AACnB,UAAM,SAAS,WAAW,KAAK;AAC/B,QAAI,CAAC,MAAM,MAAM,EAAG,QAAO;AAAA,EAC7B;AACA,SAAO;AACT;AAEA,SAAS,WAAW,QAAqD;AACvE,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI;AACF,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,cACb,aACA,UACA,oBACA,OACe;AACf,QAAM,OAAO,MAAM,gBAAgB,CAAC;AAGpC,QAAM,aAAa,WAAW,QAAQ;AACtC,QAAM,kBACJ,mBAAmB,UAAU,KAAK,SAClC,mBAAmB,eAAe,KAAK,cACvC,mBAAmB,gBAAgB,KAAK;AAC1C,QAAM,gBAAgB,gBAAgB,KAAK,cAAc;AAEzD,MAAI,CAAC,mBAAmB,CAAC,cAAe;AAGxC,QAAM,aAAsC;AAAA,IAC1C,GAAG;AAAA,EACL;AAGA,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,aAAW,QAAQ,eAAe;AAChC,QAAI,SAAS,IAAI,MAAM,QAAW;AAChC,iBAAW,IAAI,IAAI,SAAS,IAAI;AAAA,IAClC;AAAA,EACF;AAGA,UAAI,sBAAS,SAAS,UAAU,KAAK,KAAC,qBAAQ,SAAS,UAAU,GAAG;AAClE,eAAW,aAAa,SAAS;AAAA,EACnC;AAEA,QAAM,OAAgC;AAAA,IACpC,MAAM;AAAA,MACJ,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,sBAAsB,IAAI;AAE5C,QAAM,eAAe;AAAA,IACnB,OAAO,mBAAmB;AAAA,IAC1B,YAAY,mBAAmB;AAAA,IAC/B,aAAa,mBAAmB;AAAA,IAChC;AAAA,EACF;AACF;;;ACvNA;;;AHYO,IAAM,qBAAkC;AAAA,EAC7C,MAAM;AAAA,EAEN,QAAQ,CAAC;AAAA,EAET,KAAK,EAAE,QAAQ,eAAe,QAAQ,IAAI,GAAG;AAC3C,UAAM,SAAS,UAAU,eAAe,MAAM;AAC9C,UAAM,WAAW,OAAO;AAGxB,UAAM,WAAW;AAOjB,QAAI,CAAC,UAAU,aAAa,CAAC,UAAU,aAAa;AAElD,UAAI;AAGF,cAAM,aAAa,QAAQ,aAAa;AACxC,cAAM,EAAE,eAAe,WAAW,YAAY,IAAI;AAClD,cAAM,UAAU,IAAI,cAAc,SAAS,MAAM;AACjD,iBAAS,aAAa,IAAI,UAAU,OAAO;AAC3C,iBAAS,eAAe,IAAI;AAAA,UAC1B;AAAA,QACF;AAAA,MACF,SAAS,KAAK;AACZ,eAAO,MAAM,qCAAqC,GAAG,EAAE;AAAA,MACzD;AAAA,IACF;AAEA,aAAS,SAAS,CAAC;AAEnB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,OAAO,SAAS;AACzB,WAAO,MAAM,KAAK,OAAO,OAAO;AAAA,EAClC;AACF;AAEA,IAAO,gBAAQ;","names":[]}
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- var e=(e=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(e,{get:(e,t)=>("undefined"!=typeof require?require:e)[t]}):e)(function(e){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});import{getMappingValue as t,isObject as i,isString as n,isArray as r}from"@walkeros/core";var a=async function(e,{config:a,rule:l,data:s,collector:u,env:p,logger:c}){var f;const d=a.settings,v=p,y=(null==v?void 0:v.eventsApi)||d._eventsApi,m=(null==v?void 0:v.profilesApi)||d._profilesApi;if(!y||!m)return void c.warn("Klaviyo API instances not initialized");const g=d._state||{},w=(null==l?void 0:l.settings)||{},h=new Date(e.timestamp||Date.now()),N=d.email?o(await t(e,d.email,{collector:u})):void 0,I=d.externalId?o(await t(e,d.externalId,{collector:u})):void 0,b=d.phoneNumber?o(await t(e,d.phoneNumber,{collector:u})):void 0;if(!N&&!I&&!b)return void c.warn("Klaviyo requires at least one profile identifier; skipping event",{event:e.name});const x={};N&&(x.email=N),I&&(x.externalId=I),b&&(x.phoneNumber=b);const A=null!=(f=w.identify)?f:d.identify;if(void 0!==A){const n=await t(e,A,{collector:u});i(n)&&await async function(e,t,n,a){var o;const l=a.lastIdentity||{},s=function(e){if(!e)return"";try{return JSON.stringify(e)}catch(e){return""}}(t),u=n.email!==l.email||n.externalId!==l.externalId||n.phoneNumber!==l.phoneNumber,p=s!==(null!=(o=l.traitsHash)?o:"");if(!u&&!p)return;const c={...n},f=["firstName","lastName","organization","title","image","location"];for(const e of f)void 0!==t[e]&&(c[e]=t[e]);i(t.properties)&&!r(t.properties)&&(c.properties=t.properties);const d={data:{type:"profile",attributes:c}};await e.createOrUpdateProfile(d),a.lastIdentity={email:n.email,externalId:n.externalId,phoneNumber:n.phoneNumber,traitsHash:s}}(m,n,x,g)}if(!0!==(null==l?void 0:l.skip)){const r=n(null==l?void 0:l.name)?l.name:e.name,a=i(s)?{...s}:{};let o;if(void 0!==w.value){const i=function(e){if("number"==typeof e&&!isNaN(e))return e;if(n(e)){const t=parseFloat(e);if(!isNaN(t))return t}return}(await t(e,w.value,{collector:u}));void 0!==i&&(a.value=i,d.currency&&(o=d.currency))}const p={data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{...x}}},metric:{data:{type:"metric",attributes:{name:r}}},properties:a,time:h.toISOString(),...o?{valueCurrency:o}:{}}}};await y.createEvent(p)}d._state=g};function o(e){if(n(e)&&e.length>0)return e}var l={},s={type:"klaviyo",config:{},init({config:t,logger:i,env:n}){const r=function(e={},t){var i,n;const r=e.settings||{},{apiKey:a}=r;a||t.throw("Config settings apiKey missing");const o={...r,apiKey:a,email:null!=(i=r.email)?i:"user.email",externalId:null!=(n=r.externalId)?n:"user.id"};return{...e,settings:o}}(t,i),a=r.settings,o=n;if(!(null==o?void 0:o.eventsApi)||!(null==o?void 0:o.profilesApi))try{const t=e("klaviyo-api"),{ApiKeySession:i,EventsApi:n,ProfilesApi:r}=t,o=new i(a.apiKey);a._eventsApi=new n(o),a._profilesApi=new r(o)}catch(e){i.throw(`Failed to initialize Klaviyo SDK: ${e}`)}return a._state={},r},push:async(e,t)=>await a(e,t)},u=s;export{l as DestinationKlaviyo,u as default,s as destinationKlaviyo};//# sourceMappingURL=index.mjs.map
1
+ var e=(e=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(e,{get:(e,t)=>("undefined"!=typeof require?require:e)[t]}):e)(function(e){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});import{getMappingValue as t,isObject as i,isString as n,isArray as r}from"@walkeros/core";var a=async function(e,{config:a,rule:s,data:l,collector:p,env:c,logger:u}){const f=a.settings,d=c,y=d?.eventsApi||f._eventsApi,m=d?.profilesApi||f._profilesApi;if(!y||!m)return void u.warn("Klaviyo API instances not initialized");const v=f._state||{},g=s?.settings||{},w=new Date(e.timestamp||Date.now()),h=f.email?o(await t(e,f.email,{collector:p})):void 0,N=f.externalId?o(await t(e,f.externalId,{collector:p})):void 0,I=f.phoneNumber?o(await t(e,f.phoneNumber,{collector:p})):void 0;if(!h&&!N&&!I)return void u.warn("Klaviyo requires at least one profile identifier; skipping event",{event:e.name});const b={};h&&(b.email=h),N&&(b.externalId=N),I&&(b.phoneNumber=I);const x=g.identify??f.identify;if(void 0!==x){const n=await t(e,x,{collector:p});i(n)&&await async function(e,t,n,a){const o=a.lastIdentity||{},s=function(e){if(!e)return"";try{return JSON.stringify(e)}catch{return""}}(t),l=n.email!==o.email||n.externalId!==o.externalId||n.phoneNumber!==o.phoneNumber,p=s!==(o.traitsHash??"");if(!l&&!p)return;const c={...n},u=["firstName","lastName","organization","title","image","location"];for(const e of u)void 0!==t[e]&&(c[e]=t[e]);i(t.properties)&&!r(t.properties)&&(c.properties=t.properties);const f={data:{type:"profile",attributes:c}};await e.createOrUpdateProfile(f),a.lastIdentity={email:n.email,externalId:n.externalId,phoneNumber:n.phoneNumber,traitsHash:s}}(m,n,b,v)}if(!0!==s?.silent){const r=n(s?.name)?s.name:e.name,a=i(l)?{...l}:{};let o;if(void 0!==g.value){const i=function(e){if("number"==typeof e&&!isNaN(e))return e;if(n(e)){const t=parseFloat(e);if(!isNaN(t))return t}return}(await t(e,g.value,{collector:p}));void 0!==i&&(a.value=i,f.currency&&(o=f.currency))}const c={data:{type:"event",attributes:{profile:{data:{type:"profile",attributes:{...b}}},metric:{data:{type:"metric",attributes:{name:r}}},properties:a,time:w.toISOString(),...o?{valueCurrency:o}:{}}}};await y.createEvent(c)}f._state=v};function o(e){if(n(e)&&e.length>0)return e}var s={},l={type:"klaviyo",config:{},init({config:t,logger:i,env:n}){const r=function(e={},t){const i=e.settings||{},{apiKey:n}=i;n||t.throw("Config settings apiKey missing");const r={...i,apiKey:n,email:i.email??"user.email",externalId:i.externalId??"user.id"};return{...e,settings:r}}(t,i),a=r.settings,o=n;if(!o?.eventsApi||!o?.profilesApi)try{const t=e("klaviyo-api"),{ApiKeySession:i,EventsApi:n,ProfilesApi:r}=t,o=new i(a.apiKey);a._eventsApi=new n(o),a._profilesApi=new r(o)}catch(e){i.throw(`Failed to initialize Klaviyo SDK: ${e}`)}return a._state={},r},push:async(e,t)=>await a(e,t)},p=l;export{s as DestinationKlaviyo,p as default,l as destinationKlaviyo};//# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/push.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, Settings, PartialConfig } 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 } = settings;\n\n if (!apiKey) logger.throw('Config settings apiKey missing');\n\n const settingsConfig: Settings = {\n ...settings,\n apiKey,\n // Default identity resolution paths\n email: settings.email ?? 'user.email',\n externalId: settings.externalId ?? 'user.id',\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n PushFn,\n Settings,\n RuntimeState,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from './types';\nimport { getMappingValue, isObject, isString, isArray } from '@walkeros/core';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, collector, env, logger },\n) {\n const settings = config.settings as Settings;\n\n // Resolve SDK instances: prefer env mocks (testing), fall back to real\n const envTyped = env as\n | {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n }\n | undefined;\n const eventsApi = envTyped?.eventsApi || settings._eventsApi;\n const profilesApi = envTyped?.profilesApi || settings._profilesApi;\n\n if (!eventsApi || !profilesApi) {\n logger.warn('Klaviyo API instances not initialized');\n return;\n }\n\n const state: RuntimeState = settings._state || {};\n const mappingSettings = rule?.settings || {};\n const timestamp = new Date(event.timestamp || Date.now());\n\n // 1. Resolve identity from event\n const email = settings.email\n ? resolveString(await getMappingValue(event, settings.email, { collector }))\n : undefined;\n const externalId = settings.externalId\n ? resolveString(\n await getMappingValue(event, settings.externalId, { collector }),\n )\n : undefined;\n const phoneNumber = settings.phoneNumber\n ? resolveString(\n await getMappingValue(event, settings.phoneNumber, { collector }),\n )\n : undefined;\n\n if (!email && !externalId && !phoneNumber) {\n logger.warn(\n 'Klaviyo requires at least one profile identifier; skipping event',\n { event: event.name },\n );\n return;\n }\n\n // Build profile identifier object\n const profileIdentifiers: Record<string, string> = {};\n if (email) profileIdentifiers.email = email;\n if (externalId) profileIdentifiers.externalId = externalId;\n if (phoneNumber) profileIdentifiers.phoneNumber = phoneNumber;\n\n // 2. Identify -- rule-level overrides destination-level\n const identifyMapping = mappingSettings.identify ?? settings.identify;\n if (identifyMapping !== undefined) {\n const resolved = await getMappingValue(event, identifyMapping, {\n collector,\n });\n if (isObject(resolved)) {\n await applyIdentify(\n profilesApi,\n resolved as Record<string, unknown>,\n profileIdentifiers,\n state,\n );\n }\n }\n\n // 3. Track event (unless skip: true)\n if (rule?.skip !== true) {\n const eventName = isString(rule?.name) ? rule.name : event.name;\n const properties = isObject(data)\n ? { ...(data as Record<string, unknown>) }\n : {};\n\n // Handle revenue value\n let valueCurrency: string | undefined;\n if (mappingSettings.value !== undefined) {\n const resolvedValue = await getMappingValue(\n event,\n mappingSettings.value,\n {\n collector,\n },\n );\n const numericValue = toNumber(resolvedValue);\n if (numericValue !== undefined) {\n properties.value = numericValue;\n if (settings.currency) {\n valueCurrency = settings.currency;\n }\n }\n }\n\n const eventBody: Record<string, unknown> = {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: { ...profileIdentifiers },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: eventName },\n },\n },\n properties,\n time: timestamp.toISOString(),\n ...(valueCurrency ? { valueCurrency } : {}),\n },\n },\n };\n\n await eventsApi.createEvent(eventBody);\n }\n\n settings._state = state;\n};\n\nfunction resolveString(value: unknown): string | undefined {\n if (isString(value) && value.length > 0) return value;\n return undefined;\n}\n\nfunction toNumber(value: unknown): number | undefined {\n if (typeof value === 'number' && !isNaN(value)) return value;\n if (isString(value)) {\n const parsed = parseFloat(value);\n if (!isNaN(parsed)) return parsed;\n }\n return undefined;\n}\n\nfunction hashTraits(traits: Record<string, unknown> | undefined): string {\n if (!traits) return '';\n try {\n return JSON.stringify(traits);\n } catch {\n return '';\n }\n}\n\nasync function applyIdentify(\n profilesApi: KlaviyoProfilesApiMock,\n resolved: Record<string, unknown>,\n profileIdentifiers: Record<string, string>,\n state: RuntimeState,\n): Promise<void> {\n const last = state.lastIdentity || {};\n\n // Build traits hash from resolved attributes for dedup\n const traitsHash = hashTraits(resolved);\n const identityChanged =\n profileIdentifiers.email !== last.email ||\n profileIdentifiers.externalId !== last.externalId ||\n profileIdentifiers.phoneNumber !== last.phoneNumber;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n\n if (!identityChanged && !traitsChanged) return;\n\n // Build profile attributes from resolved mapping\n const attributes: Record<string, unknown> = {\n ...profileIdentifiers,\n };\n\n // Standard Klaviyo profile attributes\n const standardAttrs = [\n 'firstName',\n 'lastName',\n 'organization',\n 'title',\n 'image',\n 'location',\n ];\n for (const attr of standardAttrs) {\n if (resolved[attr] !== undefined) {\n attributes[attr] = resolved[attr];\n }\n }\n\n // Custom properties\n if (isObject(resolved.properties) && !isArray(resolved.properties)) {\n attributes.properties = resolved.properties;\n }\n\n const body: Record<string, unknown> = {\n data: {\n type: 'profile',\n attributes,\n },\n };\n\n await profilesApi.createOrUpdateProfile(body);\n\n state.lastIdentity = {\n email: profileIdentifiers.email,\n externalId: profileIdentifiers.externalId,\n phoneNumber: profileIdentifiers.phoneNumber,\n traitsHash,\n };\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\n\nexport interface Settings {\n /** Klaviyo private API key (required). Starts with 'pk_'. */\n apiKey: string;\n /** walkerOS mapping value path to resolve email from each event. */\n email?: string;\n /** walkerOS mapping value path to resolve phone number (E.164) from each event. */\n phoneNumber?: string;\n /** walkerOS mapping value path to resolve external ID from each event. */\n externalId?: string;\n /** Destination-level identify mapping. Resolves to profile attributes for upsert. */\n identify?: WalkerOSMapping.Value;\n /** Default currency for revenue events (ISO 4217, e.g. 'USD', 'EUR'). */\n currency?: string;\n /** Runtime state -- not user-facing. Mutated by init/push. */\n _eventsApi?: KlaviyoEventsApiMock;\n _profilesApi?: KlaviyoProfilesApiMock;\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n lastIdentity?: {\n email?: string;\n externalId?: string;\n phoneNumber?: string;\n traitsHash?: string;\n };\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Resolved via getMappingValue() in push().\n */\nexport interface Mapping {\n /** Per-event identify mapping. Resolves to profile attributes for upsert. */\n identify?: WalkerOSMapping.Value;\n /** Revenue value mapping. Resolves to numeric value for Klaviyo's $value. */\n value?: WalkerOSMapping.Value;\n}\n\n/**\n * Env -- optional SDK override. Production leaves this undefined and the\n * destination creates real API instances. Tests provide mocks via\n * env.eventsApi and env.profilesApi.\n */\nexport interface Env extends DestinationServer.Env {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n}\n\n/**\n * Mock-friendly interface for EventsApi.createEvent().\n */\nexport interface KlaviyoEventsApiMock {\n createEvent: (body: Record<string, unknown>) => Promise<unknown>;\n}\n\n/**\n * Mock-friendly interface for ProfilesApi.createOrUpdateProfile().\n */\nexport interface KlaviyoProfilesApiMock {\n createOrUpdateProfile: (body: Record<string, unknown>) => Promise<unknown>;\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","import type {\n Destination,\n Settings,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationKlaviyo from './types';\n\nexport const destinationKlaviyo: Destination = {\n type: 'klaviyo',\n\n config: {},\n\n init({ config: partialConfig, logger, env }) {\n const config = getConfig(partialConfig, logger);\n const settings = config.settings as Settings;\n\n // Use env mocks if provided (testing), otherwise create real SDK instances\n const envTyped = env as\n | {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n }\n | undefined;\n\n if (!envTyped?.eventsApi || !envTyped?.profilesApi) {\n // Production path: create real API instances\n try {\n // Use dynamic require to avoid bundling the SDK when not needed\n // and to allow tests to mock via jest.mock('klaviyo-api').\n const klaviyoApi = require('klaviyo-api');\n const { ApiKeySession, EventsApi, ProfilesApi } = klaviyoApi;\n const session = new ApiKeySession(settings.apiKey);\n settings._eventsApi = new EventsApi(session) as KlaviyoEventsApiMock;\n settings._profilesApi = new ProfilesApi(\n session,\n ) as KlaviyoProfilesApiMock;\n } catch (err) {\n logger.throw(`Failed to initialize Klaviyo SDK: ${err}`);\n }\n }\n\n settings._state = {};\n\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationKlaviyo;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/config.ts","../src/push.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, Settings, PartialConfig } 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 } = settings;\n\n if (!apiKey) logger.throw('Config settings apiKey missing');\n\n const settingsConfig: Settings = {\n ...settings,\n apiKey,\n // Default identity resolution paths\n email: settings.email ?? 'user.email',\n externalId: settings.externalId ?? 'user.id',\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n PushFn,\n Settings,\n RuntimeState,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from './types';\nimport { getMappingValue, isObject, isString, isArray } from '@walkeros/core';\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, collector, env, logger },\n) {\n const settings = config.settings as Settings;\n\n // Resolve SDK instances: prefer env mocks (testing), fall back to real\n const envTyped = env as\n | {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n }\n | undefined;\n const eventsApi = envTyped?.eventsApi || settings._eventsApi;\n const profilesApi = envTyped?.profilesApi || settings._profilesApi;\n\n if (!eventsApi || !profilesApi) {\n logger.warn('Klaviyo API instances not initialized');\n return;\n }\n\n const state: RuntimeState = settings._state || {};\n const mappingSettings = rule?.settings || {};\n const timestamp = new Date(event.timestamp || Date.now());\n\n // 1. Resolve identity from event\n const email = settings.email\n ? resolveString(await getMappingValue(event, settings.email, { collector }))\n : undefined;\n const externalId = settings.externalId\n ? resolveString(\n await getMappingValue(event, settings.externalId, { collector }),\n )\n : undefined;\n const phoneNumber = settings.phoneNumber\n ? resolveString(\n await getMappingValue(event, settings.phoneNumber, { collector }),\n )\n : undefined;\n\n if (!email && !externalId && !phoneNumber) {\n logger.warn(\n 'Klaviyo requires at least one profile identifier; skipping event',\n { event: event.name },\n );\n return;\n }\n\n // Build profile identifier object\n const profileIdentifiers: Record<string, string> = {};\n if (email) profileIdentifiers.email = email;\n if (externalId) profileIdentifiers.externalId = externalId;\n if (phoneNumber) profileIdentifiers.phoneNumber = phoneNumber;\n\n // 2. Identify -- rule-level overrides destination-level\n const identifyMapping = mappingSettings.identify ?? settings.identify;\n if (identifyMapping !== undefined) {\n const resolved = await getMappingValue(event, identifyMapping, {\n collector,\n });\n if (isObject(resolved)) {\n await applyIdentify(\n profilesApi,\n resolved as Record<string, unknown>,\n profileIdentifiers,\n state,\n );\n }\n }\n\n // 3. Track event (unless silent: true)\n if (rule?.silent !== true) {\n const eventName = isString(rule?.name) ? rule.name : event.name;\n const properties = isObject(data)\n ? { ...(data as Record<string, unknown>) }\n : {};\n\n // Handle revenue value\n let valueCurrency: string | undefined;\n if (mappingSettings.value !== undefined) {\n const resolvedValue = await getMappingValue(\n event,\n mappingSettings.value,\n {\n collector,\n },\n );\n const numericValue = toNumber(resolvedValue);\n if (numericValue !== undefined) {\n properties.value = numericValue;\n if (settings.currency) {\n valueCurrency = settings.currency;\n }\n }\n }\n\n const eventBody: Record<string, unknown> = {\n data: {\n type: 'event',\n attributes: {\n profile: {\n data: {\n type: 'profile',\n attributes: { ...profileIdentifiers },\n },\n },\n metric: {\n data: {\n type: 'metric',\n attributes: { name: eventName },\n },\n },\n properties,\n time: timestamp.toISOString(),\n ...(valueCurrency ? { valueCurrency } : {}),\n },\n },\n };\n\n await eventsApi.createEvent(eventBody);\n }\n\n settings._state = state;\n};\n\nfunction resolveString(value: unknown): string | undefined {\n if (isString(value) && value.length > 0) return value;\n return undefined;\n}\n\nfunction toNumber(value: unknown): number | undefined {\n if (typeof value === 'number' && !isNaN(value)) return value;\n if (isString(value)) {\n const parsed = parseFloat(value);\n if (!isNaN(parsed)) return parsed;\n }\n return undefined;\n}\n\nfunction hashTraits(traits: Record<string, unknown> | undefined): string {\n if (!traits) return '';\n try {\n return JSON.stringify(traits);\n } catch {\n return '';\n }\n}\n\nasync function applyIdentify(\n profilesApi: KlaviyoProfilesApiMock,\n resolved: Record<string, unknown>,\n profileIdentifiers: Record<string, string>,\n state: RuntimeState,\n): Promise<void> {\n const last = state.lastIdentity || {};\n\n // Build traits hash from resolved attributes for dedup\n const traitsHash = hashTraits(resolved);\n const identityChanged =\n profileIdentifiers.email !== last.email ||\n profileIdentifiers.externalId !== last.externalId ||\n profileIdentifiers.phoneNumber !== last.phoneNumber;\n const traitsChanged = traitsHash !== (last.traitsHash ?? '');\n\n if (!identityChanged && !traitsChanged) return;\n\n // Build profile attributes from resolved mapping\n const attributes: Record<string, unknown> = {\n ...profileIdentifiers,\n };\n\n // Standard Klaviyo profile attributes\n const standardAttrs = [\n 'firstName',\n 'lastName',\n 'organization',\n 'title',\n 'image',\n 'location',\n ];\n for (const attr of standardAttrs) {\n if (resolved[attr] !== undefined) {\n attributes[attr] = resolved[attr];\n }\n }\n\n // Custom properties\n if (isObject(resolved.properties) && !isArray(resolved.properties)) {\n attributes.properties = resolved.properties;\n }\n\n const body: Record<string, unknown> = {\n data: {\n type: 'profile',\n attributes,\n },\n };\n\n await profilesApi.createOrUpdateProfile(body);\n\n state.lastIdentity = {\n email: profileIdentifiers.email,\n externalId: profileIdentifiers.externalId,\n phoneNumber: profileIdentifiers.phoneNumber,\n traitsHash,\n };\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\n\nexport interface Settings {\n /** Klaviyo private API key (required). Starts with 'pk_'. */\n apiKey: string;\n /** walkerOS mapping value path to resolve email from each event. */\n email?: string;\n /** walkerOS mapping value path to resolve phone number (E.164) from each event. */\n phoneNumber?: string;\n /** walkerOS mapping value path to resolve external ID from each event. */\n externalId?: string;\n /** Destination-level identify mapping. Resolves to profile attributes for upsert. */\n identify?: WalkerOSMapping.Value;\n /** Default currency for revenue events (ISO 4217, e.g. 'USD', 'EUR'). */\n currency?: string;\n /** Runtime state -- not user-facing. Mutated by init/push. */\n _eventsApi?: KlaviyoEventsApiMock;\n _profilesApi?: KlaviyoProfilesApiMock;\n _state?: RuntimeState;\n}\n\nexport interface RuntimeState {\n lastIdentity?: {\n email?: string;\n externalId?: string;\n phoneNumber?: string;\n traitsHash?: string;\n };\n}\n\nexport type InitSettings = Partial<Settings>;\n\n/**\n * Per-rule mapping settings. Resolved via getMappingValue() in push().\n */\nexport interface Mapping {\n /** Per-event identify mapping. Resolves to profile attributes for upsert. */\n identify?: WalkerOSMapping.Value;\n /** Revenue value mapping. Resolves to numeric value for Klaviyo's $value. */\n value?: WalkerOSMapping.Value;\n}\n\n/**\n * Env -- optional SDK override. Production leaves this undefined and the\n * destination creates real API instances. Tests provide mocks via\n * env.eventsApi and env.profilesApi.\n */\nexport interface Env extends DestinationServer.Env {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n}\n\n/**\n * Mock-friendly interface for EventsApi.createEvent().\n */\nexport interface KlaviyoEventsApiMock {\n createEvent: (body: Record<string, unknown>) => Promise<unknown>;\n}\n\n/**\n * Mock-friendly interface for ProfilesApi.createOrUpdateProfile().\n */\nexport interface KlaviyoProfilesApiMock {\n createOrUpdateProfile: (body: Record<string, unknown>) => Promise<unknown>;\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","import type {\n Destination,\n Settings,\n KlaviyoEventsApiMock,\n KlaviyoProfilesApiMock,\n} from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationKlaviyo from './types';\n\nexport const destinationKlaviyo: Destination = {\n type: 'klaviyo',\n\n config: {},\n\n init({ config: partialConfig, logger, env }) {\n const config = getConfig(partialConfig, logger);\n const settings = config.settings as Settings;\n\n // Use env mocks if provided (testing), otherwise create real SDK instances\n const envTyped = env as\n | {\n eventsApi?: KlaviyoEventsApiMock;\n profilesApi?: KlaviyoProfilesApiMock;\n }\n | undefined;\n\n if (!envTyped?.eventsApi || !envTyped?.profilesApi) {\n // Production path: create real API instances\n try {\n // Use dynamic require to avoid bundling the SDK when not needed\n // and to allow tests to mock via jest.mock('klaviyo-api').\n const klaviyoApi = require('klaviyo-api');\n const { ApiKeySession, EventsApi, ProfilesApi } = klaviyoApi;\n const session = new ApiKeySession(settings.apiKey);\n settings._eventsApi = new EventsApi(session) as KlaviyoEventsApiMock;\n settings._profilesApi = new ProfilesApi(\n session,\n ) as KlaviyoProfilesApiMock;\n } catch (err) {\n logger.throw(`Failed to initialize Klaviyo SDK: ${err}`);\n }\n }\n\n settings._state = {};\n\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationKlaviyo;\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$meta": {
3
3
  "package": "@walkeros/server-destination-klaviyo",
4
- "version": "3.4.2",
4
+ "version": "4.0.0-next-1777463920154",
5
5
  "type": "destination",
6
6
  "platform": [
7
7
  "server"
@@ -15,7 +15,7 @@
15
15
  "type": "object",
16
16
  "properties": {
17
17
  "identify": {
18
- "description": "Per-event identify mapping. Resolves to profile attributes for createOrUpdateProfile(). Use with rule-level skip: true on login/signup events."
18
+ "description": "Per-event identify mapping. Resolves to profile attributes for createOrUpdateProfile(). Use with rule-level silent: true on login/signup events."
19
19
  },
20
20
  "value": {
21
21
  "description": "Revenue value mapping. Resolves to a numeric value for Klaviyo revenue tracking. Sets the value property and valueCurrency on the event."
@@ -112,22 +112,15 @@
112
112
  "consent": {
113
113
  "functional": true
114
114
  },
115
- "id": "1700000100-gr0up-1",
115
+ "id": "a2d967adbd81a6bd",
116
116
  "trigger": "load",
117
117
  "entity": "product",
118
118
  "action": "view",
119
119
  "timestamp": 1700000100,
120
120
  "timing": 3.14,
121
- "group": "gr0up",
122
- "count": 1,
123
- "version": {
124
- "source": "3.4.2",
125
- "tagging": 1
126
- },
127
121
  "source": {
128
- "type": "web",
129
- "id": "https://localhost:80",
130
- "previous_id": "http://remotehost:9001"
122
+ "type": "collector",
123
+ "schema": "4"
131
124
  }
132
125
  },
133
126
  "out": [
@@ -197,35 +190,21 @@
197
190
  "entity": "child",
198
191
  "data": {
199
192
  "is": "subordinated"
200
- },
201
- "nested": [],
202
- "context": {
203
- "element": [
204
- "child",
205
- 0
206
- ]
207
193
  }
208
194
  }
209
195
  ],
210
196
  "consent": {
211
197
  "functional": true
212
198
  },
213
- "id": "1700000104-gr0up-1",
199
+ "id": "b022c8a978173589",
214
200
  "trigger": "load",
215
201
  "entity": "page",
216
202
  "action": "view",
217
203
  "timestamp": 1700000104,
218
204
  "timing": 3.14,
219
- "group": "gr0up",
220
- "count": 1,
221
- "version": {
222
- "source": "3.4.2",
223
- "tagging": 1
224
- },
225
205
  "source": {
226
- "type": "web",
227
- "id": "https://localhost:80",
228
- "previous_id": "http://remotehost:9001"
206
+ "type": "collector",
207
+ "schema": "4"
229
208
  }
230
209
  },
231
210
  "settings": {
@@ -315,35 +294,21 @@
315
294
  "entity": "child",
316
295
  "data": {
317
296
  "is": "subordinated"
318
- },
319
- "nested": [],
320
- "context": {
321
- "element": [
322
- "child",
323
- 0
324
- ]
325
297
  }
326
298
  }
327
299
  ],
328
300
  "consent": {
329
301
  "functional": true
330
302
  },
331
- "id": "1700000105-gr0up-1",
303
+ "id": "b653ffcb110ed166",
332
304
  "trigger": "test",
333
305
  "entity": "newsletter",
334
306
  "action": "signup",
335
307
  "timestamp": 1700000105,
336
308
  "timing": 3.14,
337
- "group": "gr0up",
338
- "count": 1,
339
- "version": {
340
- "source": "3.4.2",
341
- "tagging": 1
342
- },
343
309
  "source": {
344
- "type": "web",
345
- "id": "https://localhost:80",
346
- "previous_id": "http://remotehost:9001"
310
+ "type": "collector",
311
+ "schema": "4"
347
312
  }
348
313
  },
349
314
  "settings": {},
@@ -408,22 +373,15 @@
408
373
  "consent": {
409
374
  "functional": true
410
375
  },
411
- "id": "1700000101-gr0up-1",
376
+ "id": "4ade8bf9e40ad5bc",
412
377
  "trigger": "load",
413
378
  "entity": "product",
414
379
  "action": "view",
415
380
  "timestamp": 1700000101,
416
381
  "timing": 3.14,
417
- "group": "gr0up",
418
- "count": 1,
419
- "version": {
420
- "source": "3.4.2",
421
- "tagging": 1
422
- },
423
382
  "source": {
424
- "type": "web",
425
- "id": "https://localhost:80",
426
- "previous_id": "http://remotehost:9001"
383
+ "type": "collector",
384
+ "schema": "4"
427
385
  }
428
386
  },
429
387
  "mapping": {
@@ -552,22 +510,15 @@
552
510
  "consent": {
553
511
  "functional": true
554
512
  },
555
- "id": "1700000102-gr0up-1",
513
+ "id": "88d741052c09c431",
556
514
  "trigger": "load",
557
515
  "entity": "order",
558
516
  "action": "complete",
559
517
  "timestamp": 1700000102,
560
518
  "timing": 3.14,
561
- "group": "gr0up",
562
- "count": 1,
563
- "version": {
564
- "source": "3.4.2",
565
- "tagging": 1
566
- },
567
519
  "source": {
568
- "type": "web",
569
- "id": "https://localhost:80",
570
- "previous_id": "http://remotehost:9001"
520
+ "type": "collector",
521
+ "schema": "4"
571
522
  }
572
523
  },
573
524
  "settings": {
@@ -658,39 +609,25 @@
658
609
  "entity": "child",
659
610
  "data": {
660
611
  "is": "subordinated"
661
- },
662
- "nested": [],
663
- "context": {
664
- "element": [
665
- "child",
666
- 0
667
- ]
668
612
  }
669
613
  }
670
614
  ],
671
615
  "consent": {
672
616
  "functional": true
673
617
  },
674
- "id": "1700000103-gr0up-1",
618
+ "id": "c4b46f4a61aad8f1",
675
619
  "trigger": "test",
676
620
  "entity": "user",
677
621
  "action": "login",
678
622
  "timestamp": 1700000103,
679
623
  "timing": 3.14,
680
- "group": "gr0up",
681
- "count": 1,
682
- "version": {
683
- "source": "3.4.2",
684
- "tagging": 1
685
- },
686
624
  "source": {
687
- "type": "web",
688
- "id": "https://localhost:80",
689
- "previous_id": "http://remotehost:9001"
625
+ "type": "collector",
626
+ "schema": "4"
690
627
  }
691
628
  },
692
629
  "mapping": {
693
- "skip": true,
630
+ "silent": true,
694
631
  "settings": {
695
632
  "identify": {
696
633
  "map": {
@@ -762,35 +699,21 @@
762
699
  "entity": "child",
763
700
  "data": {
764
701
  "is": "subordinated"
765
- },
766
- "nested": [],
767
- "context": {
768
- "element": [
769
- "child",
770
- 0
771
- ]
772
702
  }
773
703
  }
774
704
  ],
775
705
  "consent": {
776
706
  "functional": true
777
707
  },
778
- "id": "1700000106-gr0up-1",
708
+ "id": "53fe97017f0b4465",
779
709
  "trigger": "test",
780
710
  "entity": "debug",
781
711
  "action": "noise",
782
712
  "timestamp": 1700000106,
783
713
  "timing": 3.14,
784
- "group": "gr0up",
785
- "count": 1,
786
- "version": {
787
- "source": "3.4.2",
788
- "tagging": 1
789
- },
790
714
  "source": {
791
- "type": "web",
792
- "id": "https://localhost:80",
793
- "previous_id": "http://remotehost:9001"
715
+ "type": "collector",
716
+ "schema": "4"
794
717
  }
795
718
  },
796
719
  "mapping": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@walkeros/server-destination-klaviyo",
3
3
  "description": "Klaviyo marketing automation server destination for walkerOS (klaviyo-api SDK, events + profile upserts)",
4
- "version": "3.4.2",
4
+ "version": "4.0.0-next-1777463920154",
5
5
  "license": "MIT",
6
6
  "exports": {
7
7
  ".": {
@@ -35,11 +35,11 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "klaviyo-api": "^22.0.0",
38
- "@walkeros/core": "3.4.2",
39
- "@walkeros/server-core": "3.4.2"
38
+ "@walkeros/core": "4.0.0-next-1777463920154",
39
+ "@walkeros/server-core": "4.0.0-next-1777463920154"
40
40
  },
41
41
  "devDependencies": {
42
- "@walkeros/collector": "3.4.2"
42
+ "@walkeros/collector": "4.0.0-next-1777463920154"
43
43
  },
44
44
  "repository": {
45
45
  "url": "git+https://github.com/elbwalker/walkerOS.git",