@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 +1 -1
- package/dist/dev.d.mts +4 -4
- package/dist/dev.d.ts +4 -4
- package/dist/dev.js +1 -1
- package/dist/dev.js.map +1 -1
- package/dist/dev.mjs +1 -1
- package/dist/dev.mjs.map +1 -1
- package/dist/examples/index.d.mts +4 -4
- package/dist/examples/index.d.ts +4 -4
- package/dist/examples/index.js +1 -1
- package/dist/examples/index.mjs +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/walkerOS.json +24 -101
- package/package.json +4 -4
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 `
|
|
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)`
|
|
98
|
-
* - `profilesApi.createOrUpdateProfile(body)`
|
|
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 `
|
|
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
|
|
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)`
|
|
98
|
-
* - `profilesApi.createOrUpdateProfile(body)`
|
|
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 `
|
|
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
|
|
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
|
|
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
|
|
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)`
|
|
68
|
-
* - `profilesApi.createOrUpdateProfile(body)`
|
|
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 `
|
|
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
|
|
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;
|
package/dist/examples/index.d.ts
CHANGED
|
@@ -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)`
|
|
68
|
-
* - `profilesApi.createOrUpdateProfile(body)`
|
|
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 `
|
|
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
|
|
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;
|
package/dist/examples/index.js
CHANGED
package/dist/examples/index.mjs
CHANGED
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:()=>
|
|
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":"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","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:
|
|
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
|
package/dist/index.mjs.map
CHANGED
|
@@ -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":[]}
|
package/dist/walkerOS.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"package": "@walkeros/server-destination-klaviyo",
|
|
4
|
-
"version": "
|
|
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
|
|
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": "
|
|
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": "
|
|
129
|
-
"
|
|
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": "
|
|
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": "
|
|
227
|
-
"
|
|
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": "
|
|
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": "
|
|
345
|
-
"
|
|
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": "
|
|
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": "
|
|
425
|
-
"
|
|
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": "
|
|
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": "
|
|
569
|
-
"
|
|
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": "
|
|
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": "
|
|
688
|
-
"
|
|
689
|
-
"previous_id": "http://remotehost:9001"
|
|
625
|
+
"type": "collector",
|
|
626
|
+
"schema": "4"
|
|
690
627
|
}
|
|
691
628
|
},
|
|
692
629
|
"mapping": {
|
|
693
|
-
"
|
|
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": "
|
|
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": "
|
|
792
|
-
"
|
|
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": "
|
|
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": "
|
|
39
|
-
"@walkeros/server-core": "
|
|
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": "
|
|
42
|
+
"@walkeros/collector": "4.0.0-next-1777463920154"
|
|
43
43
|
},
|
|
44
44
|
"repository": {
|
|
45
45
|
"url": "git+https://github.com/elbwalker/walkerOS.git",
|