@inploi/sdk 1.17.0 → 1.17.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cdn/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // This is an inploi sdk script. Learn more at https://inploi.com
2
2
 
3
- "use strict";(()=>{var Se=Object.defineProperty,ve=Object.defineProperties;var Te=Object.getOwnPropertyDescriptors;var ie=Object.getOwnPropertySymbols;var Pe=Object.prototype.hasOwnProperty,xe=Object.prototype.propertyIsEnumerable;var ae=(e,n,t)=>n in e?Se(e,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[n]=t,N=(e,n)=>{for(var t in n||(n={}))Pe.call(n,t)&&ae(e,t,n[t]);if(ie)for(var t of ie(n))xe.call(n,t)&&ae(e,t,n[t]);return e},se=(e,n)=>ve(e,Te(n));var _=(e,n,t)=>new Promise((r,o)=>{var i=a=>{try{s(t.next(a))}catch(d){o(d)}},c=a=>{try{s(t.throw(a))}catch(d){o(d)}},s=a=>a.done?r(a.value):Promise.resolve(a.value).then(i,c);s((t=t.apply(e,n)).next())});function H(e,n){if(!e)throw new Error(n)}function $(e,n){return n in e}var en=new Intl.RelativeTimeFormat(void 0,{numeric:"auto"});var D="%c[inploi SDK]",F="color: #65BC67; font-weight: bold;",J={warn:(...e)=>console.warn(D,F,...e),error:(...e)=>console.error(D,F,...e),info:(...e)=>console.info(D,F,...e),log:(...e)=>console.log(D,F,...e)},Y={info:()=>{},error:()=>{},log:()=>{},warn:()=>{}};var Ee="Unauthenticated",Ie="This action is unauthorized.",v=class extends Error{constructor(t,r){super(t);this.status=r,this.name="ErrorWithStatus"}},I=class extends v{constructor(n){super(n!=null?n:"Not found"),this.name="NotFoundError",this.status=404}},k=class extends v{constructor(n,t){super(n!=null?n:"You are not authorised to perform this action."),this.name="UnauthorisedError",this.status=t!=null?t:401}},S=class extends v{constructor(t,r){let o=r?` in ${r}`:"";super(`Schema validation failed${o}`);this.issues=t;this.source=r;this.name="SchemaValidationError",this.status=400}},V=class extends v{constructor(n,t){super(n),this.name="ApiError",this.status=t!=null?t:500}},P=class extends v{constructor(t){super("Error parsing response into JSON.");this.response=t;this.name="ParsingError",this.status=500}};var ke=["message","error","errors","exception","exceptions"];function Ae(e){console.log("json",e);let n=[];if(typeof e=="object"&&e!==null){for(let t of ke)if($(e,t)){console.log("hasProp",t,e[t]);let r=e[t];typeof r=="string"&&n.push(r),Array.isArray(r)&&r.every(o=>typeof o=="string")&&n.push(...r)}}return n.length===0&&n.push("Unknown error"),n.join(", ")}function W(e,n){if(n>=300&&n<=500){let t=Ae(e);throw n===404?new I(t):t===Ee?new k("You are not authenticated.",n):t===Ie?new k(t,n):new V(t,n)}}var le=e=>{let n={Accept:"application/json","Content-Type":"application/json","x-publishable-key":e.publishableKey};return{fetch:(o,...i)=>_(void 0,[o,...i],function*(t,r={}){let c=se(N({},r),{headers:N(N({},r.headers),n)}),s=yield fetch(`${e.baseUrl}${t}`,c);if(s.status===404)throw new I;let a=yield s.json().catch(()=>_(void 0,null,function*(){throw new P(s)}));return W(a,s.status),a})}};var z="RFC3986",X={RFC1738:e=>String(e).replace(/%20/g,"+"),RFC3986:e=>String(e)},Oe="RFC1738";var Re=Array.isArray,g=(()=>{let e=[];for(let n=0;n<256;++n)e.push("%"+((n<16?"0":"")+n.toString(16)).toUpperCase());return e})();var G=1024,je=(e,n,t,r,o)=>{if(e.length===0)return e;let i=e;if(typeof e=="symbol"?i=Symbol.prototype.toString.call(e):typeof e!="string"&&(i=String(e)),t==="iso-8859-1")return escape(i).replace(/%u[0-9a-f]{4}/gi,function(s){return"%26%23"+parseInt(s.slice(2),16)+"%3B"});let c="";for(let s=0;s<i.length;s+=G){let a=i.length>=G?i.slice(s,s+G):i,d=[];for(let u=0;u<a.length;++u){let l=a.charCodeAt(u);if(l===45||l===46||l===95||l===126||l>=48&&l<=57||l>=65&&l<=90||l>=97&&l<=122||o===Oe&&(l===40||l===41)){d[d.length]=a.charAt(u);continue}if(l<128){d[d.length]=g[l];continue}if(l<2048){d[d.length]=g[192|l>>6]+g[128|l&63];continue}if(l<55296||l>=57344){d[d.length]=g[224|l>>12]+g[128|l>>6&63]+g[128|l&63];continue}u+=1,l=65536+((l&1023)<<10|a.charCodeAt(u)&1023),d[d.length]=g[240|l>>18]+g[128|l>>12&63]+g[128|l>>6&63]+g[128|l&63]}c+=d.join("")}return c};function Le(e){return!e||typeof e!="object"?!1:!!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e))}function ce(e,n){if(Re(e)){let t=[];for(let r=0;r<e.length;r+=1)t.push(n(e[r]));return t}return n(e)}var ln=Array.isArray;var Ce=Object.prototype.hasOwnProperty,de={brackets(e){return String(e)+"[]"},comma:"comma",indices(e,n){return String(e)+"["+n+"]"},repeat(e){return String(e)}},b=Array.isArray,Ne=Array.prototype.push,pe=function(e,n){Ne.apply(e,b(n)?n:[n])},De=Date.prototype.toISOString,f={addQueryPrefix:!1,allowDots:!1,allowEmptyArrays:!1,arrayFormat:"indices",charset:"utf-8",charsetSentinel:!1,delimiter:"&",encode:!0,encodeDotInKeys:!1,encoder:je,encodeValuesOnly:!1,format:z,formatter:X[z],indices:!1,serializeDate(e){return De.call(e)},skipNulls:!1,strictNullHandling:!1};function Fe(e){return typeof e=="string"||typeof e=="number"||typeof e=="boolean"||typeof e=="symbol"||typeof e=="bigint"}var Q={};function ue(e,n,t,r,o,i,c,s,a,d,u,l,h,w,m,x,R,B){let p=e,j=B,L=0,ne=!1;for(;(j=j.get(Q))!==void 0&&!ne;){let y=j.get(e);if(L+=1,typeof y!="undefined"){if(y===L)throw new RangeError("Cyclic object value");ne=!0}typeof j.get(Q)=="undefined"&&(L=0)}if(typeof d=="function"?p=d(n,p):p instanceof Date?p=h==null?void 0:h(p):t==="comma"&&b(p)&&(p=ce(p,function(y){return y instanceof Date?h==null?void 0:h(y):y})),p===null){if(i)return a&&!x?a(n,f.encoder,R,"key",w):n;p=""}if(Fe(p)||Le(p)){if(a){let y=x?n:a(n,f.encoder,R,"key",w);return[(m==null?void 0:m(y))+"="+(m==null?void 0:m(a(p,f.encoder,R,"value",w)))]}return[(m==null?void 0:m(n))+"="+(m==null?void 0:m(String(p)))]}let q=[];if(typeof p=="undefined")return q;let E;if(t==="comma"&&b(p))x&&a&&(p=ce(p,a)),E=[{value:p.length>0?p.join(",")||null:void 0}];else if(b(d))E=d;else{let y=Object.keys(p);E=u?y.sort(u):y}let te=s?String(n).replace(/\./g,"%2E"):String(n),C=r&&b(p)&&p.length===1?te+"[]":te;if(o&&b(p)&&p.length===0)return C+"[]";for(let y=0;y<E.length;++y){let T=E[y],re=typeof T=="object"&&typeof T.value!="undefined"?T.value:p[T];if(c&&re===null)continue;let U=l&&s?T.replace(/\./g,"%2E"):T,_e=b(p)?typeof t=="function"?t(C,U):C:C+(l?"."+U:"["+U+"]");B.set(e,L);let oe=new WeakMap;oe.set(Q,B),pe(q,ue(re,_e,t,r,o,i,c,s,t==="comma"&&x&&b(p)?null:a,d,u,l,h,w,m,x,R,oe))}return q}function Ve(e=f){if(typeof e.allowEmptyArrays!="undefined"&&typeof e.allowEmptyArrays!="boolean")throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");if(typeof e.encodeDotInKeys!="undefined"&&typeof e.encodeDotInKeys!="boolean")throw new TypeError("`encodeDotInKeys` option can only be `true` or `false`, when provided");if(e.encoder!==null&&typeof e.encoder!="undefined"&&typeof e.encoder!="function")throw new TypeError("Encoder has to be a function.");let n=e.charset||f.charset;if(typeof e.charset!="undefined"&&e.charset!=="utf-8"&&e.charset!=="iso-8859-1")throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");let t=z;if(typeof e.format!="undefined"){if(!Ce.call(X,e.format))throw new TypeError("Unknown format option provided.");t=e.format}let r=X[t],o=f.filter;(typeof e.filter=="function"||b(e.filter))&&(o=e.filter);let i;if(e.arrayFormat&&e.arrayFormat in de?i=e.arrayFormat:"indices"in e?i=e.indices?"indices":"repeat":i=f.arrayFormat,"commaRoundTrip"in e&&typeof e.commaRoundTrip!="boolean")throw new TypeError("`commaRoundTrip` must be a boolean, or absent");let c=typeof e.allowDots=="undefined"?e.encodeDotInKeys?!0:f.allowDots:!!e.allowDots;return{addQueryPrefix:typeof e.addQueryPrefix=="boolean"?e.addQueryPrefix:f.addQueryPrefix,allowDots:c,allowEmptyArrays:typeof e.allowEmptyArrays=="boolean"?!!e.allowEmptyArrays:f.allowEmptyArrays,arrayFormat:i,charset:n,charsetSentinel:typeof e.charsetSentinel=="boolean"?e.charsetSentinel:f.charsetSentinel,commaRoundTrip:!!e.commaRoundTrip,delimiter:typeof e.delimiter=="undefined"?f.delimiter:e.delimiter,encode:typeof e.encode=="boolean"?e.encode:f.encode,encodeDotInKeys:typeof e.encodeDotInKeys=="boolean"?e.encodeDotInKeys:f.encodeDotInKeys,encoder:typeof e.encoder=="function"?e.encoder:f.encoder,encodeValuesOnly:typeof e.encodeValuesOnly=="boolean"?e.encodeValuesOnly:f.encodeValuesOnly,filter:o,format:t,formatter:r,serializeDate:typeof e.serializeDate=="function"?e.serializeDate:f.serializeDate,skipNulls:typeof e.skipNulls=="boolean"?e.skipNulls:f.skipNulls,sort:typeof e.sort=="function"?e.sort:null,strictNullHandling:typeof e.strictNullHandling=="boolean"?e.strictNullHandling:f.strictNullHandling}}function fe(e,n={}){let t=e,r=Ve(n),o,i;typeof r.filter=="function"?(i=r.filter,t=i("",t)):b(r.filter)&&(i=r.filter,o=i);let c=[];if(typeof t!="object"||t===null)return"";let s=de[r.arrayFormat],a=s==="comma"&&r.commaRoundTrip;o||(o=Object.keys(t)),r.sort&&o.sort(r.sort);let d=new WeakMap;for(let h=0;h<o.length;++h){let w=o[h];r.skipNulls&&t[w]===null||pe(c,ue(t[w],w,s,a,r.allowEmptyArrays,r.strictNullHandling,r.skipNulls,r.encodeDotInKeys,r.encode?r.encoder:null,r.filter,r.sort,r.allowDots,r.serializeDate,r.format,r.formatter,r.encodeValuesOnly,r.charset,d))}let u=c.join(r.delimiter),l=r.addQueryPrefix===!0?"?":"";return r.charsetSentinel&&(r.charset==="iso-8859-1"?l+="utf8=%26%2310003%3B&":l+="utf8=%E2%9C%93&"),u.length>0?l+u:""}var ye="1.17.0";var K={sandbox:"https://api.staging.inploi.com",production:"https://api.inploi.com",_internal_local:"http://api.test"},me=ye;var A="isdk_session";function Z(e,n,t){let r=e["~standard"].validate(n);if(r instanceof Promise)throw new TypeError("Async schema");if(r.issues)throw new S(r.issues,t);return r.value}function Me(e,n,t){try{return{success:!0,output:Z(e,n,t)}}catch(r){if(r instanceof S)return{success:!1,issues:r.issues,source:r.source};throw r}}var O=class{constructor(n){if(this.baseUrl=K[n.environment],this.headers=new Headers({"Content-Type":"application/json",Accept:"application/json"}),n.apiKey.type==="secret"){if(typeof window!="undefined")throw new Error("Secret key cannot be used in a browser environment");this.headers.set("x-secret-key",n.apiKey.key)}else this.headers.set("x-publishable-key",n.apiKey.key);this.logger=n.logger,this._environment=n.environment}get environment(){return this._environment}getFetchParams(n,t){var a;let r=(a=t.validateIn)!=null?a:!0,{searchParams:o,body:i}=r?he(n,t):t,c=new URL(this.baseUrl),s=n.pathname;if("params"in t&&t.params)for(let[d,u]of Object.entries(t.params))s=s.replace(`:${d}`,String(u));return c.pathname=s,n.schema.searchParams&&(c.search=fe(o)),[c.toString(),{method:n.method,body:i?JSON.stringify(i):void 0,headers:this.headers,signal:t.signal}]}parseResponse(n,t){return _(this,null,function*(){var c;let r=yield t.response.json().catch(s=>{throw this.logger.error(s),new P(t.response)});if(!((c=t.validateOut)!=null?c:!0))return r;let i=Me(n.schema.response,r,"response");if(!i.success)throw W(r,t.response.status),new S(i.issues,i.source);return i.output})}request(n,t){return _(this,null,function*(){try{let r=this.getFetchParams(n,t),o=yield fetch(...r);return this.parseResponse(n,{response:o,validateOut:t.validateOut})}catch(r){throw r instanceof S?this.logger.error(r.message,r.issues):this.logger.error(r),r}})}};function M(){return{"~standard":{vendor:"inploi",version:1,validate:e=>({value:e})}}}function he(e,n){let t={searchParams:void 0,body:void 0,validateIn:!1};return e.schema.searchParams&&(t.searchParams=Z(e.schema.searchParams,"searchParams"in n?n.searchParams:{})),e.schema.body&&(t.body=Z(e.schema.body,"body"in n?n.body:{})),t}var ge=e=>{let n=new Date;return n.setTime(n.getTime()+7*24*60*60*1e3),`${A}=${e};expires=${n.toUTCString()};path=/`},qe=(e,n)=>{let t=e.get("session_id");if(n||t)return t;let r=sessionStorage.getItem(`${A}-session_id`);return typeof r=="string"?r:null},Ue=new RegExp(`${A}=([^;]+)`),be=e=>{let n=e?e.url:location.href,{searchParams:t}=new URL(n),r=t.get("anonymous_id"),o=qe(t,typeof window=="undefined");if(r)return{anonymous_id:r,session_id:o};let i=e?e.headers.get("cookie"):document.cookie;if(i){let c=Ue.exec(i),s=c==null?void 0:c[1];return{anonymous_id:s!=null?s:null,session_id:o}}return{anonymous_id:r,session_id:o}};var He=e=>typeof e!="object"||e===null?null:{anonymous_id:"anonymous_id"in e&&typeof e.anonymous_id=="string"?e.anonymous_id:null,session_id:"session_id"in e&&typeof e.session_id=="string"?e.session_id:null},$e=e=>e==="about:client"?"":e,Je={pathname:"/log",method:"POST",schema:{response:M(),body:M()}},we=({rpcClient:e,logger:n,onEvent:t})=>({log:o=>_(void 0,null,function*(){H(o.request||typeof window!="undefined","Cannot log on the server without a request. Please pass a request to `log`.");let i="request"in o&&o.request?{href:o.request.url,referrer:$e(o.request.referrer),title:""}:{href:location.href,referrer:document.referrer,title:document.title};try{let c={library:{name:"inploi-sdk",version:me},page:i},s=be(o.request),a={anonymous_id:s.anonymous_id,session_id:s.session_id,event:o.event,sent_at:new Date().toISOString(),context:c,properties:o.properties,custom_properties:o.customProperties},d=yield e.request(Je,{body:a}),u=He(d);return u!=null&&u.anonymous_id&&(a.anonymous_id=u.anonymous_id),u!=null&&u.session_id&&(a.session_id=u.session_id),typeof window!="undefined"&&a.anonymous_id&&(a.session_id&&sessionStorage.setItem(`${A}-session_id`,a.session_id.toString()),document.cookie=ge(a.anonymous_id)),t==null||t(a),{success:!0,data:a}}catch(c){return n.error("Failed to send log to API. Inspect error response of `log` for more information."),{success:!1,error:c}}}),getHeaders:o=>{let i=new Headers;return o!=null&&o.anonymous_id&&i.append("Set-Cookie",ge(o.anonymous_id)),i},getSessionInfo:be});function ee({publishableKey:e,env:n,logger:t=J,onEvent:r}){let o=le({baseUrl:K[n],publishableKey:e}),i=t===!1?Y:t,c=new O({environment:n,apiKey:{type:"publishable",key:e},logger:i}),s=we({rpcClient:c,logger:i,onEvent:r});return{register:d=>d({logger:i,apiClient:o,analytics:s,rpcClient:c,publishableKey:e}),analytics:s,apiClient:o}}typeof window.inploi!="object"&&(window.inploi={});window.process=window.process||{};window.process.env=window.process.env||{};window.process.env.NODE_ENV="production";window.inploi.initialiseSdk=ee;})();
3
+ "use strict";(()=>{var Se=Object.defineProperty,ve=Object.defineProperties;var Te=Object.getOwnPropertyDescriptors;var ie=Object.getOwnPropertySymbols;var Pe=Object.prototype.hasOwnProperty,xe=Object.prototype.propertyIsEnumerable;var ae=(e,n,t)=>n in e?Se(e,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[n]=t,N=(e,n)=>{for(var t in n||(n={}))Pe.call(n,t)&&ae(e,t,n[t]);if(ie)for(var t of ie(n))xe.call(n,t)&&ae(e,t,n[t]);return e},se=(e,n)=>ve(e,Te(n));var _=(e,n,t)=>new Promise((r,o)=>{var i=a=>{try{s(t.next(a))}catch(d){o(d)}},c=a=>{try{s(t.throw(a))}catch(d){o(d)}},s=a=>a.done?r(a.value):Promise.resolve(a.value).then(i,c);s((t=t.apply(e,n)).next())});function q(e,n){if(!e)throw new Error(n)}function H(e,n){return n in e}var nn=new Intl.RelativeTimeFormat(void 0,{numeric:"auto"});var D="%c[inploi SDK]",V="color: #65BC67; font-weight: bold;",J={warn:(...e)=>console.warn(D,V,...e),error:(...e)=>console.error(D,V,...e),info:(...e)=>console.info(D,V,...e),log:(...e)=>console.log(D,V,...e)},Y={info:()=>{},error:()=>{},log:()=>{},warn:()=>{}};var Ee="Unauthenticated",Ie="This action is unauthorized.",v=class extends Error{constructor(t,r){super(t);this.status=r,this.name="ErrorWithStatus"}},I=class extends v{constructor(n){super(n!=null?n:"Not found"),this.name="NotFoundError",this.status=404}},k=class extends v{constructor(n,t){super(n!=null?n:"You are not authorised to perform this action."),this.name="UnauthorisedError",this.status=t!=null?t:401}},S=class extends v{constructor(t,r){let o=r?` in ${r}`:"";super(`Schema validation failed${o}`);this.issues=t;this.source=r;this.name="SchemaValidationError",this.status=400}},F=class extends v{constructor(n,t){super(n),this.name="ApiError",this.status=t!=null?t:500}},P=class extends v{constructor(t){super("Error parsing response into JSON.");this.response=t;this.name="ParsingError",this.status=500}};var ke=["message","error","errors","exception","exceptions"];function Ae(e){console.log("json",e);let n=[];if(typeof e=="object"&&e!==null){for(let t of ke)if(H(e,t)){console.log("hasProp",t,e[t]);let r=e[t];typeof r=="string"&&n.push(r),Array.isArray(r)&&r.every(o=>typeof o=="string")&&n.push(...r)}}return n.length===0&&n.push("Unknown error"),n.join(", ")}function W(e,n){if(n>=300&&n<=500){let t=Ae(e);throw n===404?new I(t):t===Ee?new k("You are not authenticated.",n):t===Ie?new k(t,n):new F(t,n)}}var le=e=>{let n={Accept:"application/json","Content-Type":"application/json","x-publishable-key":e.publishableKey};return{fetch:(o,...i)=>_(void 0,[o,...i],function*(t,r={}){let c=se(N({},r),{headers:N(N({},r.headers),n)}),s=yield fetch(`${e.baseUrl}${t}`,c);if(s.status===404)throw new I;let a=yield s.json().catch(()=>_(void 0,null,function*(){throw new P(s)}));return W(a,s.status),a})}};var z="RFC3986",X={RFC1738:e=>String(e).replace(/%20/g,"+"),RFC3986:e=>String(e)},Oe="RFC1738";var Re=Array.isArray,g=(()=>{let e=[];for(let n=0;n<256;++n)e.push("%"+((n<16?"0":"")+n.toString(16)).toUpperCase());return e})();var G=1024,je=(e,n,t,r,o)=>{if(e.length===0)return e;let i=e;if(typeof e=="symbol"?i=Symbol.prototype.toString.call(e):typeof e!="string"&&(i=String(e)),t==="iso-8859-1")return escape(i).replace(/%u[0-9a-f]{4}/gi,function(s){return"%26%23"+parseInt(s.slice(2),16)+"%3B"});let c="";for(let s=0;s<i.length;s+=G){let a=i.length>=G?i.slice(s,s+G):i,d=[];for(let u=0;u<a.length;++u){let l=a.charCodeAt(u);if(l===45||l===46||l===95||l===126||l>=48&&l<=57||l>=65&&l<=90||l>=97&&l<=122||o===Oe&&(l===40||l===41)){d[d.length]=a.charAt(u);continue}if(l<128){d[d.length]=g[l];continue}if(l<2048){d[d.length]=g[192|l>>6]+g[128|l&63];continue}if(l<55296||l>=57344){d[d.length]=g[224|l>>12]+g[128|l>>6&63]+g[128|l&63];continue}u+=1,l=65536+((l&1023)<<10|a.charCodeAt(u)&1023),d[d.length]=g[240|l>>18]+g[128|l>>12&63]+g[128|l>>6&63]+g[128|l&63]}c+=d.join("")}return c};function Le(e){return!e||typeof e!="object"?!1:!!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e))}function ce(e,n){if(Re(e)){let t=[];for(let r=0;r<e.length;r+=1)t.push(n(e[r]));return t}return n(e)}var cn=Array.isArray;var Ce=Object.prototype.hasOwnProperty,de={brackets(e){return String(e)+"[]"},comma:"comma",indices(e,n){return String(e)+"["+n+"]"},repeat(e){return String(e)}},b=Array.isArray,Ne=Array.prototype.push,pe=function(e,n){Ne.apply(e,b(n)?n:[n])},De=Date.prototype.toISOString,f={addQueryPrefix:!1,allowDots:!1,allowEmptyArrays:!1,arrayFormat:"indices",charset:"utf-8",charsetSentinel:!1,delimiter:"&",encode:!0,encodeDotInKeys:!1,encoder:je,encodeValuesOnly:!1,format:z,formatter:X[z],indices:!1,serializeDate(e){return De.call(e)},skipNulls:!1,strictNullHandling:!1};function Ve(e){return typeof e=="string"||typeof e=="number"||typeof e=="boolean"||typeof e=="symbol"||typeof e=="bigint"}var Q={};function ue(e,n,t,r,o,i,c,s,a,d,u,l,h,w,m,x,R,U){let p=e,j=U,L=0,ne=!1;for(;(j=j.get(Q))!==void 0&&!ne;){let y=j.get(e);if(L+=1,typeof y!="undefined"){if(y===L)throw new RangeError("Cyclic object value");ne=!0}typeof j.get(Q)=="undefined"&&(L=0)}if(typeof d=="function"?p=d(n,p):p instanceof Date?p=h==null?void 0:h(p):t==="comma"&&b(p)&&(p=ce(p,function(y){return y instanceof Date?h==null?void 0:h(y):y})),p===null){if(i)return a&&!x?a(n,f.encoder,R,"key",w):n;p=""}if(Ve(p)||Le(p)){if(a){let y=x?n:a(n,f.encoder,R,"key",w);return[(m==null?void 0:m(y))+"="+(m==null?void 0:m(a(p,f.encoder,R,"value",w)))]}return[(m==null?void 0:m(n))+"="+(m==null?void 0:m(String(p)))]}let B=[];if(typeof p=="undefined")return B;let E;if(t==="comma"&&b(p))x&&a&&(p=ce(p,a)),E=[{value:p.length>0?p.join(",")||null:void 0}];else if(b(d))E=d;else{let y=Object.keys(p);E=u?y.sort(u):y}let te=s?String(n).replace(/\./g,"%2E"):String(n),C=r&&b(p)&&p.length===1?te+"[]":te;if(o&&b(p)&&p.length===0)return C+"[]";for(let y=0;y<E.length;++y){let T=E[y],re=typeof T=="object"&&typeof T.value!="undefined"?T.value:p[T];if(c&&re===null)continue;let $=l&&s?T.replace(/\./g,"%2E"):T,_e=b(p)?typeof t=="function"?t(C,$):C:C+(l?"."+$:"["+$+"]");U.set(e,L);let oe=new WeakMap;oe.set(Q,U),pe(B,ue(re,_e,t,r,o,i,c,s,t==="comma"&&x&&b(p)?null:a,d,u,l,h,w,m,x,R,oe))}return B}function Fe(e=f){if(typeof e.allowEmptyArrays!="undefined"&&typeof e.allowEmptyArrays!="boolean")throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");if(typeof e.encodeDotInKeys!="undefined"&&typeof e.encodeDotInKeys!="boolean")throw new TypeError("`encodeDotInKeys` option can only be `true` or `false`, when provided");if(e.encoder!==null&&typeof e.encoder!="undefined"&&typeof e.encoder!="function")throw new TypeError("Encoder has to be a function.");let n=e.charset||f.charset;if(typeof e.charset!="undefined"&&e.charset!=="utf-8"&&e.charset!=="iso-8859-1")throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");let t=z;if(typeof e.format!="undefined"){if(!Ce.call(X,e.format))throw new TypeError("Unknown format option provided.");t=e.format}let r=X[t],o=f.filter;(typeof e.filter=="function"||b(e.filter))&&(o=e.filter);let i;if(e.arrayFormat&&e.arrayFormat in de?i=e.arrayFormat:"indices"in e?i=e.indices?"indices":"repeat":i=f.arrayFormat,"commaRoundTrip"in e&&typeof e.commaRoundTrip!="boolean")throw new TypeError("`commaRoundTrip` must be a boolean, or absent");let c=typeof e.allowDots=="undefined"?e.encodeDotInKeys?!0:f.allowDots:!!e.allowDots;return{addQueryPrefix:typeof e.addQueryPrefix=="boolean"?e.addQueryPrefix:f.addQueryPrefix,allowDots:c,allowEmptyArrays:typeof e.allowEmptyArrays=="boolean"?!!e.allowEmptyArrays:f.allowEmptyArrays,arrayFormat:i,charset:n,charsetSentinel:typeof e.charsetSentinel=="boolean"?e.charsetSentinel:f.charsetSentinel,commaRoundTrip:!!e.commaRoundTrip,delimiter:typeof e.delimiter=="undefined"?f.delimiter:e.delimiter,encode:typeof e.encode=="boolean"?e.encode:f.encode,encodeDotInKeys:typeof e.encodeDotInKeys=="boolean"?e.encodeDotInKeys:f.encodeDotInKeys,encoder:typeof e.encoder=="function"?e.encoder:f.encoder,encodeValuesOnly:typeof e.encodeValuesOnly=="boolean"?e.encodeValuesOnly:f.encodeValuesOnly,filter:o,format:t,formatter:r,serializeDate:typeof e.serializeDate=="function"?e.serializeDate:f.serializeDate,skipNulls:typeof e.skipNulls=="boolean"?e.skipNulls:f.skipNulls,sort:typeof e.sort=="function"?e.sort:null,strictNullHandling:typeof e.strictNullHandling=="boolean"?e.strictNullHandling:f.strictNullHandling}}function fe(e,n={}){let t=e,r=Fe(n),o,i;typeof r.filter=="function"?(i=r.filter,t=i("",t)):b(r.filter)&&(i=r.filter,o=i);let c=[];if(typeof t!="object"||t===null)return"";let s=de[r.arrayFormat],a=s==="comma"&&r.commaRoundTrip;o||(o=Object.keys(t)),r.sort&&o.sort(r.sort);let d=new WeakMap;for(let h=0;h<o.length;++h){let w=o[h];r.skipNulls&&t[w]===null||pe(c,ue(t[w],w,s,a,r.allowEmptyArrays,r.strictNullHandling,r.skipNulls,r.encodeDotInKeys,r.encode?r.encoder:null,r.filter,r.sort,r.allowDots,r.serializeDate,r.format,r.formatter,r.encodeValuesOnly,r.charset,d))}let u=c.join(r.delimiter),l=r.addQueryPrefix===!0?"?":"";return r.charsetSentinel&&(r.charset==="iso-8859-1"?l+="utf8=%26%2310003%3B&":l+="utf8=%E2%9C%93&"),u.length>0?l+u:""}var ye="1.17.2";var K={sandbox:"https://api.staging.inploi.com",production:"https://api.inploi.com",_internal_local:"http://api.test"},me=ye;var A="isdk_session";function Z(e,n,t){let r=e["~standard"].validate(n);if(r instanceof Promise)throw new TypeError("Async schema");if(r.issues)throw new S(r.issues,t);return r.value}function Me(e,n,t){try{return{success:!0,output:Z(e,n,t)}}catch(r){if(r instanceof S)return{success:!1,issues:r.issues,source:r.source};throw r}}var O=class{constructor(n){if(this.baseUrl=K[n.environment],this.headers=new Headers({"Content-Type":"application/json",Accept:"application/json"}),n.apiKey.type==="secret"){if(typeof window!="undefined")throw new Error("Secret key cannot be used in a browser environment");this.headers.set("x-secret-key",n.apiKey.key)}else this.headers.set("x-publishable-key",n.apiKey.key);this.logger=n.logger,this._environment=n.environment}get environment(){return this._environment}getFetchParams(n,t){var a;let r=(a=t.validateIn)!=null?a:!0,{searchParams:o,body:i}=r?he(n,t):t,c=new URL(this.baseUrl),s=n.pathname;if("params"in t&&t.params)for(let[d,u]of Object.entries(t.params))s=s.replace(`:${d}`,String(u));return c.pathname=s,n.schema.searchParams&&(c.search=fe(o)),[c.toString(),{method:n.method,body:i?JSON.stringify(i):void 0,headers:this.headers,signal:t.signal}]}parseResponse(n,t){return _(this,null,function*(){var c;let r=yield t.response.json().catch(s=>{throw this.logger.error(s),new P(t.response)});if(!((c=t.validateOut)!=null?c:!0))return r;let i=Me(n.schema.response,r,"response");if(!i.success)throw W(r,t.response.status),new S(i.issues,i.source);return i.output})}request(n,t){return _(this,null,function*(){try{let r=this.getFetchParams(n,t),o=yield fetch(...r);return this.parseResponse(n,{response:o,validateOut:t.validateOut})}catch(r){throw r instanceof S?this.logger.error(r.message,r.issues):this.logger.error(r),r}})}};function M(){return{"~standard":{vendor:"inploi",version:1,validate:e=>({value:e})}}}function he(e,n){let t={searchParams:void 0,body:void 0,validateIn:!1};return e.schema.searchParams&&(t.searchParams=Z(e.schema.searchParams,"searchParams"in n?n.searchParams:{})),e.schema.body&&(t.body=Z(e.schema.body,"body"in n?n.body:{})),t}var ge=e=>{let n=new Date;return n.setTime(n.getTime()+7*24*60*60*1e3),`${A}=${e};expires=${n.toUTCString()};path=/`},$e=(e,n)=>{let t=e.get("session_id");if(n||t)return t;let r=sessionStorage.getItem(`${A}-session_id`);return typeof r=="string"?r:null},qe=new RegExp(`${A}=([^;]+)`),be=e=>{let n=e?e.url:location.href,{searchParams:t}=new URL(n),r=t.get("anonymous_id"),o=$e(t,typeof window=="undefined");if(r)return{anonymous_id:r,session_id:o};let i=e?e.headers.get("cookie"):document.cookie;if(i){let c=qe.exec(i),s=c==null?void 0:c[1];return{anonymous_id:s!=null?s:null,session_id:o}}return{anonymous_id:r,session_id:o}};var He=e=>typeof e!="object"||e===null?null:{anonymous_id:"anonymous_id"in e&&typeof e.anonymous_id=="string"?e.anonymous_id:null,session_id:"session_id"in e&&typeof e.session_id=="string"?e.session_id:null},Je=e=>e==="about:client"?"":e,Ye={pathname:"/log",method:"POST",schema:{response:M(),body:M()}},we=({rpcClient:e,logger:n,onEvent:t})=>({log:o=>_(void 0,null,function*(){q(o.request||typeof window!="undefined","Cannot log on the server without a request. Please pass a request to `log`.");let i="request"in o&&o.request?{href:o.request.url,referrer:Je(o.request.referrer),title:""}:{href:location.href,referrer:document.referrer,title:document.title};try{let c={library:{name:"inploi-sdk",version:me},page:i},s=be(o.request),a={anonymous_id:s.anonymous_id,session_id:s.session_id,event:o.event,sent_at:new Date().toISOString(),context:c,properties:o.properties,custom_properties:o.customProperties},d=yield e.request(Ye,{body:a}),u=He(d);return u!=null&&u.anonymous_id&&(a.anonymous_id=u.anonymous_id),u!=null&&u.session_id&&(a.session_id=u.session_id),typeof window!="undefined"&&a.anonymous_id&&(a.session_id&&sessionStorage.setItem(`${A}-session_id`,a.session_id.toString()),document.cookie=ge(a.anonymous_id)),t==null||t(a),{success:!0,data:a}}catch(c){return n.error("Failed to send log to API. Inspect error response of `log` for more information."),{success:!1,error:c}}}),getHeaders:o=>{let i=new Headers;return o!=null&&o.anonymous_id&&i.append("Set-Cookie",ge(o.anonymous_id)),i},getSessionInfo:be});function ee({publishableKey:e,env:n,logger:t=J,onEvent:r}){let o=le({baseUrl:K[n],publishableKey:e}),i=t===!1?Y:t,c=new O({environment:n,apiKey:{type:"publishable",key:e},logger:i}),s=we({rpcClient:c,logger:i,onEvent:r});return{register:d=>d({logger:i,apiClient:o,analytics:s,rpcClient:c,publishableKey:e,env:n}),analytics:s,apiClient:o}}typeof window.inploi!="object"&&(window.inploi={});window.process=window.process||{};window.process.env=window.process.env||{};window.process.env.NODE_ENV="production";window.inploi.initialiseSdk=ee;})();
package/dist/index.d.mts CHANGED
@@ -370,6 +370,8 @@ type PluginDependencies = {
370
370
  analytics: AnalyticsService;
371
371
  /** The publishable key used to initialise the SDK (available when registered via initialiseSdk) */
372
372
  publishableKey?: string;
373
+ /** The environment the SDK was initialised with — plugins can use this to select the correct service URL */
374
+ env?: InploiSdkEnvironment;
373
375
  };
374
376
  type InploiSdkPlugin = (dependencies: PluginDependencies) => any;
375
377
  declare const createPlugin: <T extends InploiSdkPlugin>(pluginFn: T) => T;
@@ -395,4 +397,14 @@ declare function initialiseSdk({ publishableKey, env, logger, onEvent, }: Initia
395
397
  };
396
398
  type InploiSdk = ReturnType<typeof initialiseSdk>;
397
399
 
398
- export { AnalyticsLogEvent, AnalyticsLogParams, AnalyticsOnEventCallback, AnalyticsService, ApiClient, ApiError, InitialiseInploiSdkParams, InploiRpcClient, InploiSdk, InploiSdkEnvironment, InploiSdkPlugin, Logger, NotFoundError, JsonParsingError as ParsingError, PluginParams, RpcEndpoint, SchemaValidationError, SdkError, UnauthorisedError, createPlugin, endpoint, getOrCreateAnonymousId, initialiseSdk, inploiBrandedLogger, isSdkError, noLogging, typed, validateEndpointInputs };
400
+ /**
401
+ * Generates a RFC 4122 v4 UUID.
402
+ *
403
+ * `crypto.randomUUID()` is only available in secure contexts (HTTPS). This
404
+ * utility falls back to `crypto.getRandomValues`, which is available in all
405
+ * browsing contexts including HTTP, so the SDK works on non-HTTPS staging
406
+ * environments.
407
+ */
408
+ declare const generateUUID: () => `${string}-${string}-${string}-${string}-${string}`;
409
+
410
+ export { AnalyticsLogEvent, AnalyticsLogParams, AnalyticsOnEventCallback, AnalyticsService, ApiClient, ApiError, InitialiseInploiSdkParams, InploiRpcClient, InploiSdk, InploiSdkEnvironment, InploiSdkPlugin, Logger, NotFoundError, JsonParsingError as ParsingError, PluginParams, RpcEndpoint, SchemaValidationError, SdkError, UnauthorisedError, createPlugin, endpoint, generateUUID, getOrCreateAnonymousId, initialiseSdk, inploiBrandedLogger, isSdkError, noLogging, typed, validateEndpointInputs };
package/dist/index.d.ts CHANGED
@@ -370,6 +370,8 @@ type PluginDependencies = {
370
370
  analytics: AnalyticsService;
371
371
  /** The publishable key used to initialise the SDK (available when registered via initialiseSdk) */
372
372
  publishableKey?: string;
373
+ /** The environment the SDK was initialised with — plugins can use this to select the correct service URL */
374
+ env?: InploiSdkEnvironment;
373
375
  };
374
376
  type InploiSdkPlugin = (dependencies: PluginDependencies) => any;
375
377
  declare const createPlugin: <T extends InploiSdkPlugin>(pluginFn: T) => T;
@@ -395,4 +397,14 @@ declare function initialiseSdk({ publishableKey, env, logger, onEvent, }: Initia
395
397
  };
396
398
  type InploiSdk = ReturnType<typeof initialiseSdk>;
397
399
 
398
- export { AnalyticsLogEvent, AnalyticsLogParams, AnalyticsOnEventCallback, AnalyticsService, ApiClient, ApiError, InitialiseInploiSdkParams, InploiRpcClient, InploiSdk, InploiSdkEnvironment, InploiSdkPlugin, Logger, NotFoundError, JsonParsingError as ParsingError, PluginParams, RpcEndpoint, SchemaValidationError, SdkError, UnauthorisedError, createPlugin, endpoint, getOrCreateAnonymousId, initialiseSdk, inploiBrandedLogger, isSdkError, noLogging, typed, validateEndpointInputs };
400
+ /**
401
+ * Generates a RFC 4122 v4 UUID.
402
+ *
403
+ * `crypto.randomUUID()` is only available in secure contexts (HTTPS). This
404
+ * utility falls back to `crypto.getRandomValues`, which is available in all
405
+ * browsing contexts including HTTP, so the SDK works on non-HTTPS staging
406
+ * environments.
407
+ */
408
+ declare const generateUUID: () => `${string}-${string}-${string}-${string}-${string}`;
409
+
410
+ export { AnalyticsLogEvent, AnalyticsLogParams, AnalyticsOnEventCallback, AnalyticsService, ApiClient, ApiError, InitialiseInploiSdkParams, InploiRpcClient, InploiSdk, InploiSdkEnvironment, InploiSdkPlugin, Logger, NotFoundError, JsonParsingError as ParsingError, PluginParams, RpcEndpoint, SchemaValidationError, SdkError, UnauthorisedError, createPlugin, endpoint, generateUUID, getOrCreateAnonymousId, initialiseSdk, inploiBrandedLogger, isSdkError, noLogging, typed, validateEndpointInputs };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var E=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var J=Object.prototype.hasOwnProperty;var Y=(e,n)=>{for(var r in n)E(e,r,{get:n[r],enumerable:!0})},G=(e,n,r,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of H(n))!J.call(e,o)&&o!==r&&E(e,o,{get:()=>n[o],enumerable:!(t=D(n,o))||t.enumerable});return e};var W=e=>G(E({},"__esModule",{value:!0}),e);var ie={};Y(ie,{ApiError:()=>g,InploiRpcClient:()=>y,NotFoundError:()=>l,ParsingError:()=>d,SchemaValidationError:()=>c,SdkError:()=>R,UnauthorisedError:()=>m,createPlugin:()=>V,endpoint:()=>O,getOrCreateAnonymousId:()=>U,initialiseSdk:()=>$,inploiBrandedLogger:()=>_,isSdkError:()=>B,noLogging:()=>x,typed:()=>v,validateEndpointInputs:()=>N});module.exports=W(ie);var S="%c[inploi SDK]",P="color: #65BC67; font-weight: bold;",_={warn:(...e)=>console.warn(S,P,...e),error:(...e)=>console.error(S,P,...e),info:(...e)=>console.info(S,P,...e),log:(...e)=>console.log(S,P,...e)},x={info:()=>{},error:()=>{},log:()=>{},warn:()=>{}};var V=e=>e;function w(e,n){if(!e)throw new Error(n)}function I(e,n){return n in e}var he=new Intl.RelativeTimeFormat(void 0,{numeric:"auto"});var z="Unauthenticated",X="This action is unauthorized.",u=class extends Error{constructor(r,t){super(r);this.status=t,this.name="ErrorWithStatus"}},l=class extends u{constructor(n){super(n??"Not found"),this.name="NotFoundError",this.status=404}},m=class extends u{constructor(n,r){super(n??"You are not authorised to perform this action."),this.name="UnauthorisedError",this.status=r??401}},c=class extends u{constructor(r,t){let o=t?` in ${t}`:"";super(`Schema validation failed${o}`);this.issues=r;this.source=t;this.name="SchemaValidationError",this.status=400}},g=class extends u{constructor(n,r){super(n),this.name="ApiError",this.status=r??500}},d=class extends u{constructor(r){super("Error parsing response into JSON.");this.response=r;this.name="ParsingError",this.status=500}};var Z=["message","error","errors","exception","exceptions"];function Q(e){console.log("json",e);let n=[];if(typeof e=="object"&&e!==null){for(let r of Z)if(I(e,r)){console.log("hasProp",r,e[r]);let t=e[r];typeof t=="string"&&n.push(t),Array.isArray(t)&&t.every(o=>typeof o=="string")&&n.push(...t)}}return n.length===0&&n.push("Unknown error"),n.join(", ")}function k(e,n){if(n>=300&&n<=500){let r=Q(e);throw n===404?new l(r):r===z?new m("You are not authenticated.",n):r===X?new m(r,n):new g(r,n)}}var M=e=>{let n={Accept:"application/json","Content-Type":"application/json","x-publishable-key":e.publishableKey};return{fetch:async(r,t={})=>{let o={...t,headers:{...t.headers,...n}},s=await fetch(`${e.baseUrl}${r}`,o);if(s.status===404)throw new l;let a=await s.json().catch(async()=>{throw new d(s)});return k(a,s.status),a}}},R={NotFound:l,Unauthorised:m,SchemaValidation:c,Api:g,JsonParsing:d};function B(e){return Object.values(R).some(n=>e instanceof n)}var F="1.17.0";var b={sandbox:"https://api.staging.inploi.com",production:"https://api.inploi.com",_internal_local:"http://api.test"},q=F;var h="isdk_session";var A=e=>{let n=new Date;return n.setTime(n.getTime()+7*24*60*60*1e3),`${h}=${e};expires=${n.toUTCString()};path=/`},ne=(e,n)=>{let r=e.get("session_id");if(n||r)return r;let t=sessionStorage.getItem(`${h}-session_id`);return typeof t=="string"?t:null},re=new RegExp(`${h}=([^;]+)`),L=e=>{let n=e?e.url:location.href,{searchParams:r}=new URL(n),t=r.get("anonymous_id"),o=ne(r,typeof window>"u");if(t)return{anonymous_id:t,session_id:o};let s=e?e.headers.get("cookie"):document.cookie;return s?{anonymous_id:re.exec(s)?.[1]??null,session_id:o}:{anonymous_id:t,session_id:o}},U=()=>{if(typeof window>"u")throw new Error("getOrCreateAnonymousId() can only be called in browser environment");let e=L().anonymous_id;if(e)return e;let n=crypto.randomUUID();return document.cookie=A(n),n},te=e=>typeof e!="object"||e===null?null:{anonymous_id:"anonymous_id"in e&&typeof e.anonymous_id=="string"?e.anonymous_id:null,session_id:"session_id"in e&&typeof e.session_id=="string"?e.session_id:null},oe=e=>e==="about:client"?"":e,se={pathname:"/log",method:"POST",schema:{response:v(),body:v()}},j=({rpcClient:e,logger:n,onEvent:r})=>({log:async o=>{w(o.request||typeof window<"u","Cannot log on the server without a request. Please pass a request to `log`.");let s="request"in o&&o.request?{href:o.request.url,referrer:oe(o.request.referrer),title:""}:{href:location.href,referrer:document.referrer,title:document.title};try{let a={library:{name:"inploi-sdk",version:q},page:s},p=L(o.request),i={anonymous_id:p.anonymous_id,session_id:p.session_id,event:o.event,sent_at:new Date().toISOString(),context:a,properties:o.properties,custom_properties:o.customProperties},f=await e.request(se,{body:i}),T=te(f);return T?.anonymous_id&&(i.anonymous_id=T.anonymous_id),T?.session_id&&(i.session_id=T.session_id),typeof window<"u"&&i.anonymous_id&&(i.session_id&&sessionStorage.setItem(`${h}-session_id`,i.session_id.toString()),document.cookie=A(i.anonymous_id)),r?.(i),{success:!0,data:i}}catch(a){return n.error("Failed to send log to API. Inspect error response of `log` for more information."),{success:!1,error:a}}},getHeaders:o=>{let s=new Headers;return o?.anonymous_id&&s.append("Set-Cookie",A(o.anonymous_id)),s},getSessionInfo:L});var K=require("neoqs");function C(e,n,r){let t=e["~standard"].validate(n);if(t instanceof Promise)throw new TypeError("Async schema");if(t.issues)throw new c(t.issues,r);return t.value}function ae(e,n,r){try{return{success:!0,output:C(e,n,r)}}catch(t){if(t instanceof c)return{success:!1,issues:t.issues,source:t.source};throw t}}var y=class{constructor(n){if(this.baseUrl=b[n.environment],this.headers=new Headers({"Content-Type":"application/json",Accept:"application/json"}),n.apiKey.type==="secret"){if(typeof window<"u")throw new Error("Secret key cannot be used in a browser environment");this.headers.set("x-secret-key",n.apiKey.key)}else this.headers.set("x-publishable-key",n.apiKey.key);this.logger=n.logger,this._environment=n.environment}get environment(){return this._environment}getFetchParams(n,r){let t=r.validateIn??!0,{searchParams:o,body:s}=t?N(n,r):r,a=new URL(this.baseUrl),p=n.pathname;if("params"in r&&r.params)for(let[i,f]of Object.entries(r.params))p=p.replace(`:${i}`,String(f));return a.pathname=p,n.schema.searchParams&&(a.search=(0,K.stringify)(o)),[a.toString(),{method:n.method,body:s?JSON.stringify(s):void 0,headers:this.headers,signal:r.signal}]}async parseResponse(n,r){let t=await r.response.json().catch(a=>{throw this.logger.error(a),new d(r.response)});if(!(r.validateOut??!0))return t;let s=ae(n.schema.response,t,"response");if(!s.success)throw k(t,r.response.status),new c(s.issues,s.source);return s.output}async request(n,r){try{let t=this.getFetchParams(n,r),o=await fetch(...t);return this.parseResponse(n,{response:o,validateOut:r.validateOut})}catch(t){throw t instanceof c?this.logger.error(t.message,t.issues):this.logger.error(t),t}}};function v(){return{"~standard":{vendor:"inploi",version:1,validate:e=>({value:e})}}}function O(e){return e}function N(e,n){let r={searchParams:void 0,body:void 0,validateIn:!1};return e.schema.searchParams&&(r.searchParams=C(e.schema.searchParams,"searchParams"in n?n.searchParams:{})),e.schema.body&&(r.body=C(e.schema.body,"body"in n?n.body:{})),r}function $({publishableKey:e,env:n,logger:r=_,onEvent:t}){let o=M({baseUrl:b[n],publishableKey:e}),s=r===!1?x:r,a=new y({environment:n,apiKey:{type:"publishable",key:e},logger:s}),p=j({rpcClient:a,logger:s,onEvent:t});return{register:f=>f({logger:s,apiClient:o,analytics:p,rpcClient:a,publishableKey:e}),analytics:p,apiClient:o}}0&&(module.exports={ApiError,InploiRpcClient,NotFoundError,ParsingError,SchemaValidationError,SdkError,UnauthorisedError,createPlugin,endpoint,getOrCreateAnonymousId,initialiseSdk,inploiBrandedLogger,isSdkError,noLogging,typed,validateEndpointInputs});
1
+ "use strict";var I=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var Y=Object.prototype.hasOwnProperty;var G=(e,n)=>{for(var r in n)I(e,r,{get:n[r],enumerable:!0})},W=(e,n,r,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of J(n))!Y.call(e,o)&&o!==r&&I(e,o,{get:()=>n[o],enumerable:!(t=H(n,o))||t.enumerable});return e};var z=e=>W(I({},"__esModule",{value:!0}),e);var pe={};G(pe,{ApiError:()=>g,InploiRpcClient:()=>y,NotFoundError:()=>l,ParsingError:()=>d,SchemaValidationError:()=>c,SdkError:()=>A,UnauthorisedError:()=>m,createPlugin:()=>M,endpoint:()=>C,generateUUID:()=>E,getOrCreateAnonymousId:()=>q,initialiseSdk:()=>K,inploiBrandedLogger:()=>_,isSdkError:()=>$,noLogging:()=>x,typed:()=>v,validateEndpointInputs:()=>V});module.exports=z(pe);var T="%c[inploi SDK]",P="color: #65BC67; font-weight: bold;",_={warn:(...e)=>console.warn(T,P,...e),error:(...e)=>console.error(T,P,...e),info:(...e)=>console.info(T,P,...e),log:(...e)=>console.log(T,P,...e)},x={info:()=>{},error:()=>{},log:()=>{},warn:()=>{}};var M=e=>e;function w(e,n){if(!e)throw new Error(n)}function k(e,n){return n in e}var ve=new Intl.RelativeTimeFormat(void 0,{numeric:"auto"});var X="Unauthenticated",Z="This action is unauthorized.",u=class extends Error{constructor(r,t){super(r);this.status=t,this.name="ErrorWithStatus"}},l=class extends u{constructor(n){super(n??"Not found"),this.name="NotFoundError",this.status=404}},m=class extends u{constructor(n,r){super(n??"You are not authorised to perform this action."),this.name="UnauthorisedError",this.status=r??401}},c=class extends u{constructor(r,t){let o=t?` in ${t}`:"";super(`Schema validation failed${o}`);this.issues=r;this.source=t;this.name="SchemaValidationError",this.status=400}},g=class extends u{constructor(n,r){super(n),this.name="ApiError",this.status=r??500}},d=class extends u{constructor(r){super("Error parsing response into JSON.");this.response=r;this.name="ParsingError",this.status=500}};var Q=["message","error","errors","exception","exceptions"];function ee(e){console.log("json",e);let n=[];if(typeof e=="object"&&e!==null){for(let r of Q)if(k(e,r)){console.log("hasProp",r,e[r]);let t=e[r];typeof t=="string"&&n.push(t),Array.isArray(t)&&t.every(o=>typeof o=="string")&&n.push(...t)}}return n.length===0&&n.push("Unknown error"),n.join(", ")}function R(e,n){if(n>=300&&n<=500){let r=ee(e);throw n===404?new l(r):r===X?new m("You are not authenticated.",n):r===Z?new m(r,n):new g(r,n)}}var U=e=>{let n={Accept:"application/json","Content-Type":"application/json","x-publishable-key":e.publishableKey};return{fetch:async(r,t={})=>{let o={...t,headers:{...t.headers,...n}},s=await fetch(`${e.baseUrl}${r}`,o);if(s.status===404)throw new l;let a=await s.json().catch(async()=>{throw new d(s)});return R(a,s.status),a}}},A={NotFound:l,Unauthorised:m,SchemaValidation:c,Api:g,JsonParsing:d};function $(e){return Object.values(A).some(n=>e instanceof n)}var B="1.17.2";var b={sandbox:"https://api.staging.inploi.com",production:"https://api.inploi.com",_internal_local:"http://api.test"},F=B;var h="isdk_session";var E=()=>typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"10000000-1000-4000-8000-100000000000".replace(/[018]/g,e=>(+e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>+e/4).toString(16));var L=e=>{let n=new Date;return n.setTime(n.getTime()+7*24*60*60*1e3),`${h}=${e};expires=${n.toUTCString()};path=/`},re=(e,n)=>{let r=e.get("session_id");if(n||r)return r;let t=sessionStorage.getItem(`${h}-session_id`);return typeof t=="string"?t:null},te=new RegExp(`${h}=([^;]+)`),O=e=>{let n=e?e.url:location.href,{searchParams:r}=new URL(n),t=r.get("anonymous_id"),o=re(r,typeof window>"u");if(t)return{anonymous_id:t,session_id:o};let s=e?e.headers.get("cookie"):document.cookie;return s?{anonymous_id:te.exec(s)?.[1]??null,session_id:o}:{anonymous_id:t,session_id:o}},q=()=>{if(typeof window>"u")throw new Error("getOrCreateAnonymousId() can only be called in browser environment");let e=O().anonymous_id;if(e)return e;let n=E();return document.cookie=L(n),n},oe=e=>typeof e!="object"||e===null?null:{anonymous_id:"anonymous_id"in e&&typeof e.anonymous_id=="string"?e.anonymous_id:null,session_id:"session_id"in e&&typeof e.session_id=="string"?e.session_id:null},se=e=>e==="about:client"?"":e,ae={pathname:"/log",method:"POST",schema:{response:v(),body:v()}},j=({rpcClient:e,logger:n,onEvent:r})=>({log:async o=>{w(o.request||typeof window<"u","Cannot log on the server without a request. Please pass a request to `log`.");let s="request"in o&&o.request?{href:o.request.url,referrer:se(o.request.referrer),title:""}:{href:location.href,referrer:document.referrer,title:document.title};try{let a={library:{name:"inploi-sdk",version:F},page:s},p=O(o.request),i={anonymous_id:p.anonymous_id,session_id:p.session_id,event:o.event,sent_at:new Date().toISOString(),context:a,properties:o.properties,custom_properties:o.customProperties},f=await e.request(ae,{body:i}),S=oe(f);return S?.anonymous_id&&(i.anonymous_id=S.anonymous_id),S?.session_id&&(i.session_id=S.session_id),typeof window<"u"&&i.anonymous_id&&(i.session_id&&sessionStorage.setItem(`${h}-session_id`,i.session_id.toString()),document.cookie=L(i.anonymous_id)),r?.(i),{success:!0,data:i}}catch(a){return n.error("Failed to send log to API. Inspect error response of `log` for more information."),{success:!1,error:a}}},getHeaders:o=>{let s=new Headers;return o?.anonymous_id&&s.append("Set-Cookie",L(o.anonymous_id)),s},getSessionInfo:O});var D=require("neoqs");function N(e,n,r){let t=e["~standard"].validate(n);if(t instanceof Promise)throw new TypeError("Async schema");if(t.issues)throw new c(t.issues,r);return t.value}function ie(e,n,r){try{return{success:!0,output:N(e,n,r)}}catch(t){if(t instanceof c)return{success:!1,issues:t.issues,source:t.source};throw t}}var y=class{constructor(n){if(this.baseUrl=b[n.environment],this.headers=new Headers({"Content-Type":"application/json",Accept:"application/json"}),n.apiKey.type==="secret"){if(typeof window<"u")throw new Error("Secret key cannot be used in a browser environment");this.headers.set("x-secret-key",n.apiKey.key)}else this.headers.set("x-publishable-key",n.apiKey.key);this.logger=n.logger,this._environment=n.environment}get environment(){return this._environment}getFetchParams(n,r){let t=r.validateIn??!0,{searchParams:o,body:s}=t?V(n,r):r,a=new URL(this.baseUrl),p=n.pathname;if("params"in r&&r.params)for(let[i,f]of Object.entries(r.params))p=p.replace(`:${i}`,String(f));return a.pathname=p,n.schema.searchParams&&(a.search=(0,D.stringify)(o)),[a.toString(),{method:n.method,body:s?JSON.stringify(s):void 0,headers:this.headers,signal:r.signal}]}async parseResponse(n,r){let t=await r.response.json().catch(a=>{throw this.logger.error(a),new d(r.response)});if(!(r.validateOut??!0))return t;let s=ie(n.schema.response,t,"response");if(!s.success)throw R(t,r.response.status),new c(s.issues,s.source);return s.output}async request(n,r){try{let t=this.getFetchParams(n,r),o=await fetch(...t);return this.parseResponse(n,{response:o,validateOut:r.validateOut})}catch(t){throw t instanceof c?this.logger.error(t.message,t.issues):this.logger.error(t),t}}};function v(){return{"~standard":{vendor:"inploi",version:1,validate:e=>({value:e})}}}function C(e){return e}function V(e,n){let r={searchParams:void 0,body:void 0,validateIn:!1};return e.schema.searchParams&&(r.searchParams=N(e.schema.searchParams,"searchParams"in n?n.searchParams:{})),e.schema.body&&(r.body=N(e.schema.body,"body"in n?n.body:{})),r}function K({publishableKey:e,env:n,logger:r=_,onEvent:t}){let o=U({baseUrl:b[n],publishableKey:e}),s=r===!1?x:r,a=new y({environment:n,apiKey:{type:"publishable",key:e},logger:s}),p=j({rpcClient:a,logger:s,onEvent:t});return{register:f=>f({logger:s,apiClient:o,analytics:p,rpcClient:a,publishableKey:e,env:n}),analytics:p,apiClient:o}}0&&(module.exports={ApiError,InploiRpcClient,NotFoundError,ParsingError,SchemaValidationError,SdkError,UnauthorisedError,createPlugin,endpoint,generateUUID,getOrCreateAnonymousId,initialiseSdk,inploiBrandedLogger,isSdkError,noLogging,typed,validateEndpointInputs});
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/sdk.logger.ts","../src/sdk.plugins.ts","../../core/src/common/common.utils.ts","../../core/src/common/common.currency.ts","../../core/src/common/common.datetime.ts","../src/sdk.api.ts","../package.json","../src/sdk.constants.ts","../src/sdk.analytics.ts","../src/sdk.rpc.ts","../src/sdk.ts"],"sourcesContent":["export { inploiBrandedLogger, noLogging } from './sdk.logger';\nexport type { Logger } from './sdk.logger';\n\nexport type { PluginParams, InploiSdkPlugin } from './sdk.plugins';\nexport { createPlugin } from './sdk.plugins';\n\nexport type { InploiSdkEnvironment } from './sdk.constants';\n\nexport type { ApiClient } from './sdk.api';\nexport {\n\tApiError,\n\tNotFoundError,\n\tJsonParsingError as ParsingError,\n\tUnauthorisedError,\n\tisSdkError,\n\tSchemaValidationError,\n\tSdkError,\n} from './sdk.api';\n\nexport { initialiseSdk } from './sdk';\nexport type { InitialiseInploiSdkParams, InploiSdk } from './sdk';\n\nexport type {\n\tAnalyticsService,\n\tAnalyticsLogEvent,\n\tAnalyticsLogParams,\n\tAnalyticsOnEventCallback,\n} from './sdk.analytics';\nexport { getOrCreateAnonymousId } from './sdk.analytics';\n\nexport { InploiRpcClient, endpoint, typed, validateEndpointInputs } from './sdk.rpc';\nexport type { RpcEndpoint } from './sdk.rpc';\n","export const CONSOLE_PREFIX = '%c[inploi SDK]';\nexport const CONSOLE_STYLE = 'color: #65BC67; font-weight: bold;';\n\ntype LogMessage = (...data: any[]) => void;\nexport type Logger = {\n\twarn: LogMessage;\n\terror: LogMessage;\n\tinfo: LogMessage;\n\tlog: LogMessage;\n};\n\nexport const inploiBrandedLogger: Logger = {\n\twarn: (...args) => console.warn(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\terror: (...args) => console.error(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\tinfo: (...args) => console.info(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\tlog: (...args) => console.log(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n};\n\nexport const noLogging: Logger = { info: () => void 0, error: () => void 0, log: () => void 0, warn: () => void 0 };\n","import { AnalyticsService } from './sdk.analytics';\nimport { ApiClient } from './sdk.api';\nimport { Logger } from './sdk.logger';\nimport { InploiRpcClient } from './sdk.rpc';\n\nexport type PluginParams = {\n\tapiClient: ApiClient;\n\tlogger: Logger;\n};\n\nexport type Plugin<T extends string, P extends Record<string, unknown>> = {\n\tpluginName: T;\n\tpure_createActions: (params: PluginParams) => P;\n};\n\ntype PluginDependencies = {\n\tapiClient: ApiClient;\n\trpcClient: InploiRpcClient;\n\tlogger: Logger;\n\tanalytics: AnalyticsService;\n\t/** The publishable key used to initialise the SDK (available when registered via initialiseSdk) */\n\tpublishableKey?: string;\n};\n\nexport type InploiSdkPlugin = (dependencies: PluginDependencies) => any;\n\nexport const createPlugin = <T extends InploiSdkPlugin>(pluginFn: T) => pluginFn;\n","export const exhaustive = (value: never) => {\n\tthrow new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`);\n};\n\nexport function invariant(condition: any, message?: string): asserts condition {\n\tif (condition) {\n\t\treturn;\n\t}\n\n\tthrow new Error(message);\n}\n\nexport const uniqueOrThrow = <T>(array: T[]) => {\n\tconst uniqueValues = new Set(array);\n\n\tif (array.length !== uniqueValues.size) {\n\t\tthrow new Error('Duplicate values found');\n\t}\n\treturn true;\n};\n\nexport const uniqueByPropertyOrThrow =\n\t<T extends PropertyKey>(propertyKey: T) =>\n\t(array: { [K in T]: any }[]) => {\n\t\tconst values = array.map(item => item[propertyKey]);\n\t\tconst uniqueValues = new Set(values);\n\n\t\tif (values.length !== uniqueValues.size) {\n\t\t\tthrow new Error(`Duplicate values found for property: ${propertyKey.toString()}`);\n\t\t}\n\t\treturn true;\n\t};\n\n/**\n * A destructive way to ensure an object has a property.\n * This is useful when working with unknowns.\n */\nexport function hasProp<K extends PropertyKey>(data: object, prop: K): data is Record<K, unknown> {\n\treturn prop in data;\n}\n\n/**\n * A sort of type-safe way to check whether a key exists in an object.\n */\nexport function isKeyInObj<O extends Record<string, unknown>>(key: PropertyKey, obj: O): key is keyof O {\n\treturn key in obj;\n}\n","type TFunction = (key: 'competitive' | 'invalid_salary' | 'from' | 'up_to') => string;\n\ninterface SalaryParams {\n\tpay: string | null;\n\tpay_min: string | null;\n\tpay_mask: boolean;\n\tpay_max: string | null;\n\tpay_type: 'ANNUALLY' | 'HOURLY' | 'MONTHLY' | 'WEEKLY' | 'DAILY' | null;\n\tpay_currency: string;\n\tpay_display: boolean;\n}\n\nconst payPeriods: Record<NonNullable<SalaryParams['pay_type']>, string> = {\n\tANNUALLY: 'per year',\n\tDAILY: 'per day',\n\tHOURLY: 'per hour',\n\tMONTHLY: 'per month',\n\tWEEKLY: 'per week',\n};\n\nexport const getSalaryAsText = (params: {\n\tsalary: SalaryParams;\n\tconfig: { locales: string | string[] | undefined };\n\tt?: TFunction;\n}) => {\n\tconst { salary, config, t = s => s } = params;\n\tconst numberFormatter = new Intl.NumberFormat(config.locales, {\n\t\tstyle: 'currency',\n\t\tcurrency: salary.pay_currency,\n\t\ttrailingZeroDisplay: 'stripIfInteger',\n\t});\n\tif (salary.pay_display === false) return undefined;\n\tif (salary.pay === null && salary.pay_min === null && salary.pay_max === null) return undefined;\n\tif (salary.pay_mask) return t('competitive');\n\n\tif (salary.pay_max && Number.isNaN(+salary.pay_max)) return t('invalid_salary');\n\tif (salary.pay_min && Number.isNaN(+salary.pay_min)) return t('invalid_salary');\n\tif (salary.pay && Number.isNaN(+salary.pay)) return t('invalid_salary');\n\n\tconst period = salary.pay_type && salary.pay_type in payPeriods ? payPeriods[salary.pay_type] : undefined;\n\n\tif (salary.pay) return [numberFormatter.format(+salary.pay), period].filter(Boolean).join(' ');\n\n\tif (salary.pay_max && salary.pay_min)\n\t\treturn [numberFormatter.formatRange(+salary.pay_min, +salary.pay_max), period].filter(Boolean).join(' ') || '';\n\n\tif (salary.pay_max)\n\t\treturn `${t('up_to')} ${[numberFormatter.format(+salary.pay_max), period].filter(Boolean).join(' ')}`;\n\tif (salary.pay_min)\n\t\treturn `${t('from')} ${[numberFormatter.format(+salary.pay_min), period].filter(Boolean).join(' ')}`;\n\treturn t('invalid_salary');\n};\n","type TFunction = (key: 'today' | 'over_30_days_ago' | 'in_over_30_days') => string;\n\ntype Params = {\n\tfrom?: Date;\n\tto: string | number | Date;\n\tformatter?: Intl.RelativeTimeFormat;\n\tt?: TFunction;\n};\n\nconst DEFAULT_FORMATTER = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' });\n/** From a date, calculates the relative time difference from now */\nexport const getRelativeTimeDifference = ({\n\tfrom = new Date(),\n\tto,\n\tformatter = DEFAULT_FORMATTER,\n\tt = s => s,\n}: Params) => {\n\tconst then = to instanceof Date ? to : new Date(to);\n\tconst diff = then.getTime() - from.getTime();\n\n\tconst diffIn = {\n\t\tdays: Math.round(diff / 1000 / 60 / 60 / 24),\n\t\tmonths: Math.round(diff / 1000 / 60 / 60 / 24 / 30),\n\t};\n\n\tif (diffIn.days === 0) return t('today');\n\tif (Math.abs(diffIn.days) < 30) return formatter.format(diffIn.days, 'days');\n\tif (Math.abs(diffIn.days) < 3) return formatter.format(diffIn.months, 'months');\n\treturn diffIn.months < 0 ? t('over_30_days_ago') : t('in_over_30_days');\n};\n","import { hasProp } from '@inploi/core/common';\nimport { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport const unauthenticatedMessage = 'Unauthenticated';\nexport const unauthorisedMessage = 'This action is unauthorized.';\n\nexport class ErrorWithStatus extends Error {\n\tpublic status?: number;\n\tconstructor(message?: string, status?: number) {\n\t\tsuper(message);\n\t\tthis.status = status;\n\t\tthis.name = 'ErrorWithStatus';\n\t}\n}\n\nexport class NotFoundError extends ErrorWithStatus {\n\tconstructor(message?: string) {\n\t\tsuper(message ?? 'Not found');\n\t\tthis.name = 'NotFoundError';\n\t\tthis.status = 404;\n\t}\n}\n\nexport class UnauthorisedError extends ErrorWithStatus {\n\tconstructor(message?: string, status?: number) {\n\t\tsuper(message ?? 'You are not authorised to perform this action.');\n\t\tthis.name = 'UnauthorisedError';\n\t\tthis.status = status ?? 401;\n\t}\n}\n\nexport class SchemaValidationError extends ErrorWithStatus {\n\tconstructor(\n\t\tpublic issues: readonly StandardSchemaV1.Issue[],\n\t\tpublic source?: 'body' | 'searchParams' | 'response',\n\t) {\n\t\tconst sourceText = source ? ` in ${source}` : '';\n\t\tsuper(`Schema validation failed${sourceText}`);\n\t\tthis.name = 'SchemaValidationError';\n\t\tthis.status = 400;\n\t}\n}\n\nexport class ApiError extends ErrorWithStatus {\n\tconstructor(message: string, status?: number) {\n\t\tsuper(message);\n\t\tthis.name = 'ApiError';\n\t\tthis.status = status ?? 500;\n\t}\n}\n\nexport class JsonParsingError extends ErrorWithStatus {\n\tconstructor(public response?: Response) {\n\t\tsuper('Error parsing response into JSON.');\n\t\tthis.name = 'ParsingError';\n\t\tthis.status = 500;\n\t}\n}\n\n/** @deprecated - use `JsonParsingError` instead */\nexport class ParsingError extends JsonParsingError {}\n\nexport type ApiClient = {\n\tfetch: (pathname: string, options?: RequestInit) => Promise<unknown>;\n};\n\nconst ERROR_MESSAGE_KEYS = ['message', 'error', 'errors', 'exception', 'exceptions'] as const;\nfunction getErrorMessageFromJson(json: unknown): string {\n\tconsole.log('json', json);\n\tconst messages: string[] = [];\n\tif (typeof json === 'object' && json !== null) {\n\t\tfor (const key of ERROR_MESSAGE_KEYS) {\n\t\t\tif (hasProp(json, key)) {\n\t\t\t\tconsole.log('hasProp', key, json[key]);\n\t\t\t\tconst value = json[key];\n\t\t\t\tif (typeof value === 'string') messages.push(value);\n\t\t\t\tif (Array.isArray(value) && value.every((item): item is string => typeof item === 'string'))\n\t\t\t\t\tmessages.push(...value);\n\t\t\t}\n\t\t}\n\t}\n\tif (messages.length === 0) messages.push('Unknown error');\n\treturn messages.join(', ');\n}\n\n/** Throws branded errors when API returns a known error. */\nexport function handleApiExceptions(json: unknown, status: number) {\n\tif (status >= 300 && status <= 500) {\n\t\tconst message = getErrorMessageFromJson(json);\n\t\tif (status === 404) {\n\t\t\tthrow new NotFoundError(message);\n\t\t}\n\t\tif (message === unauthenticatedMessage) {\n\t\t\tthrow new UnauthorisedError('You are not authenticated.', status);\n\t\t}\n\t\tif (message === unauthorisedMessage) {\n\t\t\tthrow new UnauthorisedError(message, status);\n\t\t}\n\t\tthrow new ApiError(message, status);\n\t}\n}\n\nexport const createApiClient = (params: { baseUrl: string; publishableKey: string }): ApiClient => {\n\tconst defaultHeaders: HeadersInit = {\n\t\tAccept: 'application/json',\n\t\t'Content-Type': 'application/json',\n\t\t'x-publishable-key': params.publishableKey,\n\t};\n\n\treturn {\n\t\t/** Fetches from a pathname with a pre-established base path.\n\t\t * Parses received output as JSON, and throw if one of the common error messages is received.\n\t\t */\n\t\tfetch: async (pathname, options = {}) => {\n\t\t\tconst init = { ...options, headers: { ...options.headers, ...defaultHeaders } };\n\t\t\tconst response = await fetch(`${params.baseUrl}${pathname}`, init);\n\t\t\tif (response.status === 404) throw new NotFoundError();\n\n\t\t\tconst json = await response.json().catch(async () => {\n\t\t\t\tthrow new JsonParsingError(response);\n\t\t\t});\n\n\t\t\thandleApiExceptions(json, response.status);\n\n\t\t\t// We’re assuming no other exceptions have happened.\n\t\t\treturn json;\n\t\t},\n\t};\n};\n\nexport const SdkError = {\n\tNotFound: NotFoundError,\n\tUnauthorised: UnauthorisedError,\n\tSchemaValidation: SchemaValidationError,\n\tApi: ApiError,\n\tJsonParsing: JsonParsingError,\n};\n\nexport function isSdkError(error: unknown): error is (typeof SdkError)[keyof typeof SdkError] {\n\treturn Object.values(SdkError).some(ErrorClass => error instanceof ErrorClass);\n}\n","{\n\t\"name\": \"@inploi/sdk\",\n\t\"version\": \"1.17.0\",\n\t\"main\": \"dist/index.js\",\n\t\"types\": \"dist/index.d.ts\",\n\t\"license\": \"MIT\",\n\t\"files\": [\n\t\t\"/dist\",\n\t\t\"/cdn\"\n\t],\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"require\": \"./dist/index.js\",\n\t\t\t\"import\": \"./dist/index.mjs\",\n\t\t\t\"types\": \"./dist/index.d.ts\"\n\t\t}\n\t},\n\t\"scripts\": {\n\t\t\"build:npm\": \"tsup --dts --dts-resolve\",\n\t\t\"build:cdn\": \"tsup --config tsup.cdn.config.ts\",\n\t\t\"build\": \"concurrently 'pnpm run build:npm' 'pnpm run build:cdn'\",\n\t\t\"dev\": \"tsup --watch --config tsup.cdn.config.ts\",\n\t\t\"check\": \"eslint src --fix --max-warnings 0 && tsc\",\n\t\t\"test\": \"bun test\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@happy-dom/global-registrator\": \"^13.6.2\",\n\t\t\"@inploi/core\": \"workspace:*\",\n\t\t\"@total-typescript/ts-reset\": \"^0.5.1\",\n\t\t\"@types/bun\": \"^1.2.5\",\n\t\t\"@types/react\": \"^18.2.33\",\n\t\t\"@types/react-dom\": \"^18.2.14\",\n\t\t\"autoprefixer\": \"^10.4.16\",\n\t\t\"concurrently\": \"9.1.2\",\n\t\t\"eslint\": \"^7.32.0\",\n\t\t\"eslint-config-custom\": \"workspace:*\",\n\t\t\"happy-dom\": \"^12.6.0\",\n\t\t\"ts-toolbelt\": \"^9.6.0\",\n\t\t\"tsconfig\": \"workspace:*\",\n\t\t\"tsup\": \"^7.2.0\"\n\t},\n\t\"dependencies\": {\n\t\t\"@standard-schema/spec\": \"^1.0.0\",\n\t\t\"neoqs\": \"^6.13.0\"\n\t}\n}\n","import { version } from '../package.json';\n\n/**\n * The environment the SDK should run in.\n * - `production`: data will be stored and displayed on dashboards\n * - `sandbox`: data will be stored temporarily and purged periodically\n */\nexport type InploiSdkEnvironment = 'production' | 'sandbox';\n\nexport const ENV_TO_API_URL: Record<InploiSdkEnvironment, string> = {\n\tsandbox: 'https://api.staging.inploi.com',\n\tproduction: 'https://api.inploi.com',\n\t// @ts-expect-error - local test environment\n\t_internal_local: 'http://api.test',\n};\n\nexport const ANALYTICS_VERSION = version;\n\nexport const LOG_PATHNAME = '/log';\n\nexport const ANALYTICS_COOKIE_NAME = 'isdk_session';\n","import type { ResponseObj } from '@inploi/core/common';\nimport { invariant } from '@inploi/core/common';\n\nimport { InploiRpcClient, Logger, endpoint, typed } from '.';\nimport { ANALYTICS_COOKIE_NAME, ANALYTICS_VERSION } from './sdk.constants';\n\nconst formatCookie = (value: string) => {\n\tconst now = new Date();\n\tnow.setTime(now.getTime() + 7 * 24 * 60 * 60 * 1000); // 7 days expiration\n\n\treturn `${ANALYTICS_COOKIE_NAME}=${value};expires=${now.toUTCString()};path=/`;\n};\n\ntype FlowProperties = { flow_id: string; flow_version: number; flow_session_id: string; flow_build: number };\n\ntype JobProperties = {\n\tid: string;\n\tid_type: 'internal' | 'external';\n};\n\nexport type AnalyticsLogParams =\n\t| {\n\t\t\tevent: 'VIEW_JOB';\n\t\t\tproperties: { job: JobProperties };\n\t }\n\t| {\n\t\t\tevent: 'FLOW_REDIRECT';\n\t\t\tproperties: { href: string; job: JobProperties | undefined } & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'FLOW_START' | 'FLOW_END';\n\t\t\tproperties: { job: JobProperties | undefined } & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'FLOW_SUBMIT';\n\t\t\tproperties: {\n\t\t\t\tservice: string;\n\t\t\t\tresponse: {\n\t\t\t\t\tstatus: number;\n\t\t\t\t\tpayload: unknown;\n\t\t\t\t};\n\t\t\t\tjob: JobProperties | undefined;\n\t\t\t} & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'SUBMIT_FORM' | 'VIEW_PAGE';\n\t\t\tproperties?: {\n\t\t\t\tjob: JobProperties | undefined;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'IDENTIFY';\n\t\t\tproperties: {\n\t\t\t\tidentifier: string;\n\t\t\t\tfirst_name?: string;\n\t\t\t\tlast_name?: string;\n\t\t\t\tphone_number?: string;\n\t\t\t\temail?: string;\n\t\t\t\tcustom_traits?: Record<string, unknown>;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_PAGINATE';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_SETTLE';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_JOB_CLICK';\n\t\t\tproperties: {\n\t\t\t\tjob_id: number;\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'VIEW_SEARCH';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'FEEDBACK';\n\t\t\tproperties: {\n\t\t\t\tkey: string;\n\t\t\t\tscore?: -1 | 0 | 1;\n\t\t\t\tcomment?: string;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'LINK_CLICK';\n\t\t\tproperties: {\n\t\t\t\ttarget_href: string;\n\t\t\t\tjob_id: string | undefined;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'INTERACTION';\n\t\t\tproperties: {\n\t\t\t\ttag: string;\n\t\t\t};\n\t };\n\nexport type AnalyticsLogEvent = AnalyticsLogParams['event'];\n\ntype EventPropertyMap = {\n\t[Param in AnalyticsLogParams as Param['event']]: Omit<Param, 'event'>;\n};\n\ntype AnalyticsContext = {\n\tlibrary: {\n\t\tname: 'inploi-sdk';\n\t\tversion: string;\n\t};\n\tpage: {\n\t\thref: string;\n\t\treferrer: string;\n\t\ttitle: string;\n\t};\n};\n\ntype TrackPayload<P = EventPropertyMap[keyof EventPropertyMap]['properties']> = {\n\tanonymous_id: string | null;\n\tsession_id: string | null;\n\tevent: AnalyticsLogEvent;\n\tsent_at: string;\n\tcontext: AnalyticsContext;\n\tproperties: P;\n\tcustom_properties?: Record<string, unknown>;\n};\n\ntype LogFnParams<T extends keyof EventPropertyMap> = {\n\tevent: T;\n\tcustomProperties?: Record<string, unknown>;\n\t/** Passing a request will make logging possible on a server environment. */\n\trequest?: Request;\n} & EventPropertyMap[T];\n\ntype LogFn = <TEvent extends keyof EventPropertyMap>(\n\tparams: LogFnParams<TEvent>,\n) => Promise<ResponseObj<TrackPayload<EventPropertyMap[TEvent]['properties']>>>;\n\nexport type AnalyticsService = {\n\tlog: LogFn;\n\t/** From a log payload data, generate headers to use in server environments to update the anonymous_id */\n\tgetHeaders: (payload?: TrackPayload) => Headers;\n\tgetSessionInfo: typeof getSessionInfo;\n};\n\nconst getSessionId = (searchParams: URLSearchParams, isServer: boolean) => {\n\tconst fromSearchParams = searchParams.get('session_id');\n\tif (isServer) return fromSearchParams;\n\tif (fromSearchParams) return fromSearchParams;\n\tconst fromSessionStorage = sessionStorage.getItem(`${ANALYTICS_COOKIE_NAME}-session_id`);\n\tif (typeof fromSessionStorage === 'string') return fromSessionStorage;\n\treturn null;\n};\n\nconst cookieRegex = new RegExp(`${ANALYTICS_COOKIE_NAME}=([^;]+)`);\nconst getSessionInfo = (request?: Request) => {\n\tconst href = request ? request.url : location.href;\n\tconst { searchParams } = new URL(href);\n\tconst anonymous_id = searchParams.get('anonymous_id');\n\tconst session_id = getSessionId(searchParams, typeof window === 'undefined');\n\n\t// If there's an anonymous_id in the search params, use it\n\tif (anonymous_id)\n\t\treturn {\n\t\t\tanonymous_id,\n\t\t\tsession_id,\n\t\t};\n\n\t// If there's a cookie, use it\n\tconst cookie = request ? request.headers.get('cookie') : document.cookie;\n\tif (cookie) {\n\t\tconst match = cookieRegex.exec(cookie);\n\t\tconst anonymous_id = match?.[1];\n\t\treturn {\n\t\t\tanonymous_id: anonymous_id ?? null,\n\t\t\tsession_id,\n\t\t};\n\t}\n\n\t// Otherwise, return what we have\n\treturn {\n\t\tanonymous_id,\n\t\tsession_id,\n\t};\n};\n\n/**\n * Get or create a persistent anonymous ID.\n *\n * This is the universal identifier that bridges:\n * - SDK analytics (Laravel tracking)\n * - Agent conversations (Durable Object routing)\n * - Identity resolution\n *\n * The ID is:\n * - Generated client-side if none exists\n * - Persisted in cookie for 7 days\n * - The same across all SDK plugins\n *\n * @returns The anonymous ID (existing or newly generated)\n */\nexport const getOrCreateAnonymousId = (): string => {\n\t// Server-side: cannot generate, return empty (should not happen in normal flow)\n\tif (typeof window === 'undefined') {\n\t\tthrow new Error('getOrCreateAnonymousId() can only be called in browser environment');\n\t}\n\n\t// Check existing sources first\n\tconst existing = getSessionInfo().anonymous_id;\n\tif (existing) return existing;\n\n\t// Generate new ID and immediately persist to cookie\n\tconst newId = crypto.randomUUID();\n\tdocument.cookie = formatCookie(newId);\n\treturn newId;\n};\n\nconst getSessionInfoFromResponse = (response: unknown) => {\n\tif (typeof response !== 'object' || response === null) return null;\n\treturn {\n\t\tanonymous_id:\n\t\t\t'anonymous_id' in response && typeof response.anonymous_id === 'string' ? response.anonymous_id : null,\n\t\tsession_id: 'session_id' in response && typeof response.session_id === 'string' ? response.session_id : null,\n\t};\n};\n\nconst serverReferrer = (referrer: typeof Request.prototype.referrer) => {\n\tif (referrer === 'about:client') return '';\n\treturn referrer;\n};\n\nconst analyticsLogEndpoint = endpoint({\n\tpathname: '/log',\n\tmethod: 'POST',\n\tschema: {\n\t\tresponse: typed<unknown>(),\n\t\tbody: typed<TrackPayload>(),\n\t},\n});\n\nexport type AnalyticsOnEventCallback = (event: AnalyticsLogParams) => void;\n\nexport const createAnalyticsService = ({\n\trpcClient,\n\tlogger,\n\tonEvent,\n}: {\n\tlogger: Logger;\n\trpcClient: InploiRpcClient;\n\tonEvent?: AnalyticsOnEventCallback;\n}): AnalyticsService => {\n\tconst logFn: LogFn = async params => {\n\t\tinvariant(\n\t\t\tparams.request || typeof window !== 'undefined',\n\t\t\t'Cannot log on the server without a request. Please pass a request to `log`.',\n\t\t);\n\n\t\t// if there’s a request, use it instead of browser APIs\n\t\tconst page =\n\t\t\t'request' in params && params.request ?\n\t\t\t\t{\n\t\t\t\t\thref: params.request.url,\n\t\t\t\t\treferrer: serverReferrer(params.request.referrer),\n\t\t\t\t\ttitle: '',\n\t\t\t\t}\n\t\t\t:\t{\n\t\t\t\t\thref: location.href,\n\t\t\t\t\treferrer: document.referrer,\n\t\t\t\t\ttitle: document.title,\n\t\t\t\t};\n\n\t\ttry {\n\t\t\tconst context: AnalyticsContext = {\n\t\t\t\tlibrary: {\n\t\t\t\t\tname: 'inploi-sdk',\n\t\t\t\t\tversion: ANALYTICS_VERSION,\n\t\t\t\t},\n\t\t\t\tpage,\n\t\t\t};\n\n\t\t\tconst sessionInfo = getSessionInfo(params.request);\n\t\t\tconst payload: TrackPayload = {\n\t\t\t\tanonymous_id: sessionInfo.anonymous_id,\n\t\t\t\tsession_id: sessionInfo.session_id,\n\t\t\t\tevent: params.event,\n\t\t\t\tsent_at: new Date().toISOString(),\n\t\t\t\tcontext,\n\t\t\t\tproperties: params.properties,\n\t\t\t\tcustom_properties: params.customProperties,\n\t\t\t};\n\n\t\t\tconst responseJson = await rpcClient.request(analyticsLogEndpoint, {\n\t\t\t\tbody: payload,\n\t\t\t});\n\n\t\t\tconst newSession = getSessionInfoFromResponse(responseJson);\n\t\t\tif (newSession?.anonymous_id) {\n\t\t\t\tpayload.anonymous_id = newSession.anonymous_id;\n\t\t\t}\n\t\t\tif (newSession?.session_id) {\n\t\t\t\tpayload.session_id = newSession.session_id;\n\t\t\t}\n\n\t\t\tif (typeof window !== 'undefined' && payload.anonymous_id) {\n\t\t\t\tif (payload.session_id) {\n\t\t\t\t\tsessionStorage.setItem(`${ANALYTICS_COOKIE_NAME}-session_id`, payload.session_id.toString());\n\t\t\t\t}\n\t\t\t\tdocument.cookie = formatCookie(payload.anonymous_id);\n\t\t\t}\n\n\t\t\tonEvent?.(payload as AnalyticsLogParams);\n\t\t\treturn { success: true, data: payload };\n\t\t} catch (e) {\n\t\t\t/** We dont’t log any PII on the console */\n\t\t\tlogger.error('Failed to send log to API. Inspect error response of `log` for more information.');\n\t\t\treturn { success: false, error: e };\n\t\t}\n\t};\n\n\treturn {\n\t\tlog: logFn,\n\t\tgetHeaders: payload => {\n\t\t\tconst headers = new Headers();\n\t\t\tif (!payload?.anonymous_id) return headers;\n\n\t\t\theaders.append('Set-Cookie', formatCookie(payload.anonymous_id));\n\t\t\treturn headers;\n\t\t},\n\t\tgetSessionInfo,\n\t};\n};\n","import type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { stringify } from 'neoqs';\n\nimport { JsonParsingError, SchemaValidationError, handleApiExceptions } from './sdk.api';\nimport { ENV_TO_API_URL, InploiSdkEnvironment } from './sdk.constants';\nimport { Logger } from './sdk.logger';\n\ntype RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\n\n/** Extract parameter names from a pathname string */\ntype ExtractParamNames<T extends string> =\n\tT extends `${infer _Before}:${infer Param}/${infer After}` ? Param | ExtractParamNames<`/${After}`>\n\t: T extends `${infer _Before}:${infer Param}` ? Param\n\t: never;\n\n/** Create params object from parameter names */\ntype ExtractPathParams<T extends string> =\n\tstring extends T ? Record<string, string | number>\n\t: ExtractParamNames<T> extends never ? Record<string, never>\n\t: { [K in ExtractParamNames<T>]: string | number };\n\n/** Parses a StandardSchemaV1 schema and input into an output. */\nexport function parse<T extends StandardSchemaV1>(\n\tschema: T,\n\tinput: StandardSchemaV1.InferInput<T>,\n\tsource?: 'body' | 'searchParams' | 'response',\n): StandardSchemaV1.InferOutput<T> {\n\tconst result = schema['~standard'].validate(input);\n\tif (result instanceof Promise) {\n\t\tthrow new TypeError('Async schema');\n\t}\n\n\tif (result.issues) {\n\t\tthrow new SchemaValidationError(result.issues, source);\n\t}\n\n\treturn result.value;\n}\n\n/** Parses a StandardSchemaV1 schema and input into an output, returning a success flag and issues if the parse fails. */\nexport function safeParse<T extends StandardSchemaV1>(\n\tschema: T,\n\tinput: StandardSchemaV1.InferInput<T>,\n\tsource?: 'body' | 'searchParams' | 'response',\n):\n\t| {\n\t\t\tsuccess: true;\n\t\t\toutput: StandardSchemaV1.InferOutput<T>;\n\t }\n\t| {\n\t\t\tsuccess: false;\n\t\t\tissues: readonly StandardSchemaV1.Issue[];\n\t\t\tsource?: 'body' | 'searchParams' | 'response';\n\t } {\n\ttry {\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\toutput: parse(schema, input, source),\n\t\t};\n\t} catch (e) {\n\t\tif (e instanceof SchemaValidationError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tissues: e.issues,\n\t\t\t\tsource: e.source,\n\t\t\t};\n\t\t}\n\t\tthrow e;\n\t}\n}\n\nexport interface InploiRpcClientParams {\n\tenvironment: InploiSdkEnvironment;\n\tlogger: Logger;\n\tapiKey:\n\t\t| {\n\t\t\t\t/** Makes the API call with an x-secret-key header\n\t\t\t\t * This will error if used in a browser environment.\n\t\t\t\t */\n\t\t\t\ttype: 'secret';\n\t\t\t\tkey: string;\n\t\t }\n\t\t| {\n\t\t\t\t/** Makes the API call with an x-publishable-key header\n\t\t\t\t * This can be called in a browser or server environment.\n\t\t\t\t */\n\t\t\t\ttype: 'publishable';\n\t\t\t\tkey: string;\n\t\t };\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\ntype NonReducibleUnknown = {} | null | undefined;\ntype LooseAutocomplete<T extends BaseType, BaseType> = T | BaseType;\n\n/** RPC client for making API calls to the Inploi API. */\nexport class InploiRpcClient {\n\tprivate baseUrl: string;\n\tprivate headers: Headers;\n\tprivate logger: Logger;\n\tprivate _environment: InploiSdkEnvironment;\n\n\tconstructor(params: InploiRpcClientParams) {\n\t\tthis.baseUrl = ENV_TO_API_URL[params.environment];\n\t\tthis.headers = new Headers({\n\t\t\t'Content-Type': 'application/json',\n\t\t\tAccept: 'application/json',\n\t\t});\n\t\tif (params.apiKey.type === 'secret') {\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\tthrow new Error('Secret key cannot be used in a browser environment');\n\t\t\t}\n\t\t\tthis.headers.set('x-secret-key', params.apiKey.key);\n\t\t} else {\n\t\t\tthis.headers.set('x-publishable-key', params.apiKey.key);\n\t\t}\n\t\tthis.logger = params.logger;\n\t\tthis._environment = params.environment;\n\t}\n\n\tget environment() {\n\t\treturn this._environment;\n\t}\n\n\t/** Gets params for a fetch request to the given endpoint */\n\tgetFetchParams<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: T extends RpcEndpoint<infer _, infer _TPathname, infer TPathParams, infer TSearch, infer TBody> ?\n\t\t\tGetSchemaValues<{\n\t\t\t\tbody: TBody;\n\t\t\t\tsearchParams: TSearch;\n\t\t\t\tparams: TPathParams;\n\t\t\t}> & {\n\t\t\t\tsignal?: AbortSignal;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the inputs against the schema.\n\t\t\t\t * If you want to skip validation (e.g.: already validated yourself or with `validateEndpontInputs`), set this to false.\n\t\t\t\t */\n\t\t\t\tvalidateIn?: boolean;\n\t\t\t}\n\t\t:\tnever,\n\t): [url: string, options: RequestInit] {\n\t\tconst validateIn = options.validateIn ?? true;\n\t\tconst { searchParams, body } = validateIn ? validateEndpointInputs(endpoint, options) : options;\n\n\t\tconst url = new URL(this.baseUrl);\n\n\t\t// Replace path parameters in pathname\n\t\tlet pathname = endpoint.pathname;\n\t\tif ('params' in options && options.params) {\n\t\t\tfor (const [key, value] of Object.entries(options.params)) {\n\t\t\t\tpathname = pathname.replace(`:${key}`, String(value));\n\t\t\t}\n\t\t}\n\t\turl.pathname = pathname;\n\n\t\tif (endpoint.schema.searchParams) {\n\t\t\turl.search = stringify(searchParams);\n\t\t}\n\n\t\treturn [\n\t\t\turl.toString(),\n\t\t\t{\n\t\t\t\tmethod: endpoint.method,\n\t\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t\t\theaders: this.headers,\n\t\t\t\tsignal: options.signal,\n\t\t\t},\n\t\t];\n\t}\n\n\t/** Parses a response against an endpoint’s response schema, considering common errors thrown from the API.\n\t * @throws {JsonParsingError} - If the response is not valid JSON.\n\t * @throws {SchemaValidationError} - If the response does not match the schema.\n\t * @throws {ApiError} - If the API responded with an error message.\n\t */\n\tasync parseResponse<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: {\n\t\t\tresponse: Response;\n\t\t\t/**\n\t\t\t * Whether to validate the response against the schema.\n\t\t\t * This is meant more as an escape hatch for when the response is not as expected and you want to handle it separately yourself.\n\t\t\t * ⚠️ This will lead to potential type/runtime mismatch as it does not verify the response against the schema.\n\t\t\t */\n\t\t\tvalidateOut?: boolean;\n\t\t},\n\t): Promise<StandardSchemaV1.InferOutput<T['schema']['response']>> {\n\t\tconst json = await options.response.json().catch(e => {\n\t\t\tthis.logger.error(e);\n\t\t\tthrow new JsonParsingError(options.response);\n\t\t});\n\n\t\tconst validateOut = options.validateOut ?? true;\n\t\tif (!validateOut) return json as StandardSchemaV1.InferOutput<T['schema']['response']>;\n\n\t\tconst result = safeParse(endpoint.schema.response, json, 'response');\n\t\tif (!result.success) {\n\t\t\thandleApiExceptions(json, options.response.status);\n\t\t\tthrow new SchemaValidationError(result.issues, result.source);\n\t\t}\n\n\t\treturn result.output as StandardSchemaV1.InferOutput<T['schema']['response']>;\n\t}\n\n\t/** Fetches, parses and validates an API endpoint.\n\t * Logs errors and throws them again so that the caller can handle them.\n\t *\n\t * @throws {JsonParsingError} - If the response is not valid JSON.\n\t * @throws {SchemaValidationError} - If the searchParams, body or response does not match the schema.\n\t * @throws {ApiError} - If the API responded with an error message.\n\t * @throws {UnauthorisedError} - If the request is unauthorised either by missing key or unmet permissions.\n\t * @throws {NotFoundError} - If the endpoint is not found.\n\t * @throws {Error} - Another unhandled error.\n\t */\n\tasync request<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: T extends RpcEndpoint<infer _, infer _TPathname, infer TPathParams, infer TSearch, infer TBody> ?\n\t\t\tGetSchemaValues<{\n\t\t\t\tbody: TBody;\n\t\t\t\tsearchParams: TSearch;\n\t\t\t\tparams: TPathParams;\n\t\t\t}> & {\n\t\t\t\tsignal?: AbortSignal;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the inputs against the schema.\n\t\t\t\t * If you want to skip validation (e.g.: already validated yourself or with `validateEndpontInputs`), set this to false.\n\t\t\t\t */\n\t\t\t\tvalidateIn?: boolean;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the response against the schema.\n\t\t\t\t * This is meant more as an escape hatch for when the response is not as expected and you want to handle it separately yourself.\n\t\t\t\t * ⚠️ This will lead to potential type/runtime mismatch as it does not verify the response against the schema.\n\t\t\t\t */\n\t\t\t\tvalidateOut?: boolean;\n\t\t\t}\n\t\t:\tnever,\n\t): Promise<StandardSchemaV1.InferOutput<T['schema']['response']>> {\n\t\ttry {\n\t\t\tconst fetchParams = this.getFetchParams(endpoint, options);\n\t\t\tconst response = await fetch(...fetchParams);\n\t\t\treturn this.parseResponse(endpoint, { response, validateOut: options.validateOut });\n\t\t} catch (e) {\n\t\t\tif (e instanceof SchemaValidationError) {\n\t\t\t\tthis.logger.error(e.message, e.issues);\n\t\t\t} else {\n\t\t\t\tthis.logger.error(e);\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t}\n}\n\ntype GetSchemaValues<T extends { searchParams: any; body: any; params?: any }> = {\n\t[K in keyof T as T[K] extends never ? never\n\t: T[K] extends Record<string, never> ? never\n\t: K]: T[K] extends never ? never : LooseAutocomplete<T[K], NonReducibleUnknown>;\n};\n\n/**\n * Typed but *not runtime validated* schema\n * useful for type-checking the schema without bundling validation schemas\n */\nexport function typed<T>(): StandardSchemaV1<T, T> {\n\treturn {\n\t\t'~standard': {\n\t\t\tvendor: 'inploi',\n\t\t\tversion: 1,\n\t\t\tvalidate: input => {\n\t\t\t\treturn {\n\t\t\t\t\tvalue: input as T,\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t};\n}\n\nexport interface RpcEndpoint<\n\tTMethod extends RequestMethod = RequestMethod,\n\tTPathname extends string = string,\n\tTPathParams = any,\n\tTSearch = any,\n\tTBody = any,\n\tTResponse = any,\n> {\n\tpathname: TPathname;\n\tmethod: TMethod;\n\theaders?: Headers;\n\tschema: {\n\t\tsearchParams?: StandardSchemaV1<TSearch, TSearch>;\n\t\tbody?: StandardSchemaV1<TBody, TBody>;\n\t\tresponse: StandardSchemaV1<TResponse, TResponse>;\n\t};\n\t/** Type-only property to store path parameter types */\n\treadonly __pathParams?: TPathParams;\n}\n\nexport function endpoint<\n\tTMethod extends RequestMethod,\n\tTPathname extends string,\n\tTSearch extends StandardSchemaV1 | never = never,\n\tTBody extends StandardSchemaV1 | never = never,\n\tTResponse extends StandardSchemaV1 | never = never,\n>(endpoint: {\n\tpathname: TPathname;\n\tmethod: TMethod;\n\theaders?: Headers;\n\tschema: {\n\t\tsearchParams?: TSearch;\n\t\tbody?: TBody;\n\t\tresponse: TResponse;\n\t};\n}) {\n\ttype PathParams = ExtractPathParams<TPathname>;\n\treturn endpoint as RpcEndpoint<\n\t\tTMethod,\n\t\tTPathname,\n\t\tPathParams,\n\t\tStandardSchemaV1.InferInput<TSearch>,\n\t\tStandardSchemaV1.InferInput<TBody>,\n\t\tStandardSchemaV1.InferOutput<TResponse>\n\t>;\n}\n\n/** Validates the inputs for an endpoint ahead of time\n * Useful when you need to validate and throw earlier, or use the inputs for something other than the API call.\n */\nexport function validateEndpointInputs<T extends RpcEndpoint>(\n\tendpoint: T,\n\toptions: GetSchemaValues<{ body: unknown; searchParams: unknown }>,\n) {\n\tconst validatedInputs = {\n\t\tsearchParams: undefined,\n\t\tbody: undefined,\n\t\tvalidateIn: false,\n\t} as T extends RpcEndpoint<infer _, infer __, infer ___, infer TSearch, infer TBody> ?\n\t\tGetSchemaValues<{\n\t\t\tbody: TBody;\n\t\t\tsearchParams: TSearch;\n\t\t}> & {\n\t\t\tvalidateIn: false;\n\t\t}\n\t:\tnever;\n\n\tif (endpoint.schema.searchParams) {\n\t\tvalidatedInputs.searchParams = parse(\n\t\t\tendpoint.schema.searchParams,\n\t\t\t'searchParams' in options ? options.searchParams : {},\n\t\t);\n\t}\n\n\tif (endpoint.schema.body) {\n\t\tvalidatedInputs.body = parse(endpoint.schema.body, 'body' in options ? options.body : {});\n\t}\n\n\treturn validatedInputs;\n}\n","import { AnalyticsOnEventCallback, createAnalyticsService } from './sdk.analytics';\nimport { createApiClient } from './sdk.api';\nimport { ENV_TO_API_URL, InploiSdkEnvironment } from './sdk.constants';\nimport { Logger, inploiBrandedLogger, noLogging } from './sdk.logger';\nimport { InploiSdkPlugin } from './sdk.plugins';\nimport { InploiRpcClient } from './sdk.rpc';\n\nexport type InitialiseInploiSdkParams = {\n\t/** Your public API key for the inploi SDK. */\n\tpublishableKey: string;\n\t/** Which app environment to run. This ultimately affects which inploi endpoints to gather data are going to be used.\n\t * Anything other than `production` should be considered a development environment and the data periodicaly purged. */\n\tenv: InploiSdkEnvironment;\n\t/** Logger object that handles logging of different levels.\n\t * You can override this to use your own logger, or to disable logging altogether by passing`false`.\n\t * @default inploiBrandedLogger\n\t * */\n\tlogger?: Logger | false;\n\n\t/** When provided, this callback will be called with every event that is logged to the analytics service. */\n\tonEvent?: AnalyticsOnEventCallback;\n};\n\nexport function initialiseSdk({\n\tpublishableKey,\n\tenv,\n\tlogger = inploiBrandedLogger,\n\tonEvent,\n}: InitialiseInploiSdkParams) {\n\t/** @deprecated - use `rpcClient` instead */\n\tconst apiClient = createApiClient({ baseUrl: ENV_TO_API_URL[env], publishableKey });\n\tconst loggerService = logger === false ? noLogging : logger;\n\tconst rpcClient = new InploiRpcClient({\n\t\tenvironment: env,\n\t\tapiKey: { type: 'publishable', key: publishableKey },\n\t\tlogger: loggerService,\n\t});\n\tconst analytics = createAnalyticsService({ rpcClient, logger: loggerService, onEvent });\n\n\tconst register = <P extends InploiSdkPlugin>(plugin: P): ReturnType<P> => {\n\t\treturn plugin({ logger: loggerService, apiClient, analytics, rpcClient, publishableKey });\n\t};\n\n\treturn { register, analytics, apiClient };\n}\n\nexport type InploiSdk = ReturnType<typeof initialiseSdk>;\n"],"mappings":"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","names":["src_exports","__export","ApiError","InploiRpcClient","NotFoundError","JsonParsingError","SchemaValidationError","SdkError","UnauthorisedError","createPlugin","endpoint","getOrCreateAnonymousId","initialiseSdk","inploiBrandedLogger","isSdkError","noLogging","typed","validateEndpointInputs","__toCommonJS","CONSOLE_PREFIX","CONSOLE_STYLE","inploiBrandedLogger","args","noLogging","createPlugin","pluginFn","invariant","condition","message","hasProp","data","prop","DEFAULT_FORMATTER","unauthenticatedMessage","unauthorisedMessage","ErrorWithStatus","message","status","NotFoundError","UnauthorisedError","SchemaValidationError","issues","source","sourceText","ApiError","JsonParsingError","response","ERROR_MESSAGE_KEYS","getErrorMessageFromJson","json","messages","key","hasProp","value","item","handleApiExceptions","status","message","NotFoundError","unauthenticatedMessage","UnauthorisedError","unauthorisedMessage","ApiError","createApiClient","params","defaultHeaders","pathname","options","init","response","JsonParsingError","SdkError","SchemaValidationError","isSdkError","error","ErrorClass","version","ENV_TO_API_URL","ANALYTICS_VERSION","version","ANALYTICS_COOKIE_NAME","formatCookie","value","now","ANALYTICS_COOKIE_NAME","getSessionId","searchParams","isServer","fromSearchParams","fromSessionStorage","cookieRegex","getSessionInfo","request","href","anonymous_id","session_id","cookie","getOrCreateAnonymousId","existing","newId","getSessionInfoFromResponse","response","serverReferrer","referrer","analyticsLogEndpoint","typed","createAnalyticsService","rpcClient","logger","onEvent","params","invariant","page","context","ANALYTICS_VERSION","sessionInfo","payload","responseJson","newSession","e","headers","import_neoqs","parse","schema","input","source","result","SchemaValidationError","safeParse","e","InploiRpcClient","params","ENV_TO_API_URL","endpoint","options","validateIn","searchParams","body","validateEndpointInputs","url","pathname","key","value","json","JsonParsingError","handleApiExceptions","fetchParams","response","typed","validatedInputs","initialiseSdk","publishableKey","env","logger","inploiBrandedLogger","onEvent","apiClient","createApiClient","ENV_TO_API_URL","loggerService","noLogging","rpcClient","InploiRpcClient","analytics","createAnalyticsService","plugin"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/sdk.logger.ts","../src/sdk.plugins.ts","../../core/src/common/common.utils.ts","../../core/src/common/common.currency.ts","../../core/src/common/common.datetime.ts","../src/sdk.api.ts","../package.json","../src/sdk.constants.ts","../src/sdk.uuid.ts","../src/sdk.analytics.ts","../src/sdk.rpc.ts","../src/sdk.ts"],"sourcesContent":["export { inploiBrandedLogger, noLogging } from './sdk.logger';\nexport type { Logger } from './sdk.logger';\n\nexport type { PluginParams, InploiSdkPlugin } from './sdk.plugins';\nexport { createPlugin } from './sdk.plugins';\n\nexport type { InploiSdkEnvironment } from './sdk.constants';\n\nexport type { ApiClient } from './sdk.api';\nexport {\n\tApiError,\n\tNotFoundError,\n\tJsonParsingError as ParsingError,\n\tUnauthorisedError,\n\tisSdkError,\n\tSchemaValidationError,\n\tSdkError,\n} from './sdk.api';\n\nexport { initialiseSdk } from './sdk';\nexport type { InitialiseInploiSdkParams, InploiSdk } from './sdk';\n\nexport type {\n\tAnalyticsService,\n\tAnalyticsLogEvent,\n\tAnalyticsLogParams,\n\tAnalyticsOnEventCallback,\n} from './sdk.analytics';\nexport { getOrCreateAnonymousId } from './sdk.analytics';\n\nexport { InploiRpcClient, endpoint, typed, validateEndpointInputs } from './sdk.rpc';\nexport type { RpcEndpoint } from './sdk.rpc';\n\nexport { generateUUID } from './sdk.uuid';\n","export const CONSOLE_PREFIX = '%c[inploi SDK]';\nexport const CONSOLE_STYLE = 'color: #65BC67; font-weight: bold;';\n\ntype LogMessage = (...data: any[]) => void;\nexport type Logger = {\n\twarn: LogMessage;\n\terror: LogMessage;\n\tinfo: LogMessage;\n\tlog: LogMessage;\n};\n\nexport const inploiBrandedLogger: Logger = {\n\twarn: (...args) => console.warn(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\terror: (...args) => console.error(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\tinfo: (...args) => console.info(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\tlog: (...args) => console.log(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n};\n\nexport const noLogging: Logger = { info: () => void 0, error: () => void 0, log: () => void 0, warn: () => void 0 };\n","import { AnalyticsService } from './sdk.analytics';\nimport { ApiClient } from './sdk.api';\nimport { InploiSdkEnvironment } from './sdk.constants';\nimport { Logger } from './sdk.logger';\nimport { InploiRpcClient } from './sdk.rpc';\n\nexport type PluginParams = {\n\tapiClient: ApiClient;\n\tlogger: Logger;\n};\n\nexport type Plugin<T extends string, P extends Record<string, unknown>> = {\n\tpluginName: T;\n\tpure_createActions: (params: PluginParams) => P;\n};\n\ntype PluginDependencies = {\n\tapiClient: ApiClient;\n\trpcClient: InploiRpcClient;\n\tlogger: Logger;\n\tanalytics: AnalyticsService;\n\t/** The publishable key used to initialise the SDK (available when registered via initialiseSdk) */\n\tpublishableKey?: string;\n\t/** The environment the SDK was initialised with — plugins can use this to select the correct service URL */\n\tenv?: InploiSdkEnvironment;\n};\n\nexport type InploiSdkPlugin = (dependencies: PluginDependencies) => any;\n\nexport const createPlugin = <T extends InploiSdkPlugin>(pluginFn: T) => pluginFn;\n","export const exhaustive = (value: never) => {\n\tthrow new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`);\n};\n\nexport function invariant(condition: any, message?: string): asserts condition {\n\tif (condition) {\n\t\treturn;\n\t}\n\n\tthrow new Error(message);\n}\n\nexport const uniqueOrThrow = <T>(array: T[]) => {\n\tconst uniqueValues = new Set(array);\n\n\tif (array.length !== uniqueValues.size) {\n\t\tthrow new Error('Duplicate values found');\n\t}\n\treturn true;\n};\n\nexport const uniqueByPropertyOrThrow =\n\t<T extends PropertyKey>(propertyKey: T) =>\n\t(array: { [K in T]: any }[]) => {\n\t\tconst values = array.map(item => item[propertyKey]);\n\t\tconst uniqueValues = new Set(values);\n\n\t\tif (values.length !== uniqueValues.size) {\n\t\t\tthrow new Error(`Duplicate values found for property: ${propertyKey.toString()}`);\n\t\t}\n\t\treturn true;\n\t};\n\n/**\n * A destructive way to ensure an object has a property.\n * This is useful when working with unknowns.\n */\nexport function hasProp<K extends PropertyKey>(data: object, prop: K): data is Record<K, unknown> {\n\treturn prop in data;\n}\n\n/**\n * A sort of type-safe way to check whether a key exists in an object.\n */\nexport function isKeyInObj<O extends Record<string, unknown>>(key: PropertyKey, obj: O): key is keyof O {\n\treturn key in obj;\n}\n","type TFunction = (key: 'competitive' | 'invalid_salary' | 'from' | 'up_to') => string;\n\ninterface SalaryParams {\n\tpay: string | null;\n\tpay_min: string | null;\n\tpay_mask: boolean;\n\tpay_max: string | null;\n\tpay_type: 'ANNUALLY' | 'HOURLY' | 'MONTHLY' | 'WEEKLY' | 'DAILY' | null;\n\tpay_currency: string;\n\tpay_display: boolean;\n}\n\nconst payPeriods: Record<NonNullable<SalaryParams['pay_type']>, string> = {\n\tANNUALLY: 'per year',\n\tDAILY: 'per day',\n\tHOURLY: 'per hour',\n\tMONTHLY: 'per month',\n\tWEEKLY: 'per week',\n};\n\nexport const getSalaryAsText = (params: {\n\tsalary: SalaryParams;\n\tconfig: { locales: string | string[] | undefined };\n\tt?: TFunction;\n}) => {\n\tconst { salary, config, t = s => s } = params;\n\tconst numberFormatter = new Intl.NumberFormat(config.locales, {\n\t\tstyle: 'currency',\n\t\tcurrency: salary.pay_currency,\n\t\ttrailingZeroDisplay: 'stripIfInteger',\n\t});\n\tif (salary.pay_display === false) return undefined;\n\tif (salary.pay === null && salary.pay_min === null && salary.pay_max === null) return undefined;\n\tif (salary.pay_mask) return t('competitive');\n\n\tif (salary.pay_max && Number.isNaN(+salary.pay_max)) return t('invalid_salary');\n\tif (salary.pay_min && Number.isNaN(+salary.pay_min)) return t('invalid_salary');\n\tif (salary.pay && Number.isNaN(+salary.pay)) return t('invalid_salary');\n\n\tconst period = salary.pay_type && salary.pay_type in payPeriods ? payPeriods[salary.pay_type] : undefined;\n\n\tif (salary.pay) return [numberFormatter.format(+salary.pay), period].filter(Boolean).join(' ');\n\n\tif (salary.pay_max && salary.pay_min)\n\t\treturn [numberFormatter.formatRange(+salary.pay_min, +salary.pay_max), period].filter(Boolean).join(' ') || '';\n\n\tif (salary.pay_max)\n\t\treturn `${t('up_to')} ${[numberFormatter.format(+salary.pay_max), period].filter(Boolean).join(' ')}`;\n\tif (salary.pay_min)\n\t\treturn `${t('from')} ${[numberFormatter.format(+salary.pay_min), period].filter(Boolean).join(' ')}`;\n\treturn t('invalid_salary');\n};\n","type TFunction = (key: 'today' | 'over_30_days_ago' | 'in_over_30_days') => string;\n\ntype Params = {\n\tfrom?: Date;\n\tto: string | number | Date;\n\tformatter?: Intl.RelativeTimeFormat;\n\tt?: TFunction;\n};\n\nconst DEFAULT_FORMATTER = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' });\n/** From a date, calculates the relative time difference from now */\nexport const getRelativeTimeDifference = ({\n\tfrom = new Date(),\n\tto,\n\tformatter = DEFAULT_FORMATTER,\n\tt = s => s,\n}: Params) => {\n\tconst then = to instanceof Date ? to : new Date(to);\n\tconst diff = then.getTime() - from.getTime();\n\n\tconst diffIn = {\n\t\tdays: Math.round(diff / 1000 / 60 / 60 / 24),\n\t\tmonths: Math.round(diff / 1000 / 60 / 60 / 24 / 30),\n\t};\n\n\tif (diffIn.days === 0) return t('today');\n\tif (Math.abs(diffIn.days) < 30) return formatter.format(diffIn.days, 'days');\n\tif (Math.abs(diffIn.days) < 3) return formatter.format(diffIn.months, 'months');\n\treturn diffIn.months < 0 ? t('over_30_days_ago') : t('in_over_30_days');\n};\n","import { hasProp } from '@inploi/core/common';\nimport { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport const unauthenticatedMessage = 'Unauthenticated';\nexport const unauthorisedMessage = 'This action is unauthorized.';\n\nexport class ErrorWithStatus extends Error {\n\tpublic status?: number;\n\tconstructor(message?: string, status?: number) {\n\t\tsuper(message);\n\t\tthis.status = status;\n\t\tthis.name = 'ErrorWithStatus';\n\t}\n}\n\nexport class NotFoundError extends ErrorWithStatus {\n\tconstructor(message?: string) {\n\t\tsuper(message ?? 'Not found');\n\t\tthis.name = 'NotFoundError';\n\t\tthis.status = 404;\n\t}\n}\n\nexport class UnauthorisedError extends ErrorWithStatus {\n\tconstructor(message?: string, status?: number) {\n\t\tsuper(message ?? 'You are not authorised to perform this action.');\n\t\tthis.name = 'UnauthorisedError';\n\t\tthis.status = status ?? 401;\n\t}\n}\n\nexport class SchemaValidationError extends ErrorWithStatus {\n\tconstructor(\n\t\tpublic issues: readonly StandardSchemaV1.Issue[],\n\t\tpublic source?: 'body' | 'searchParams' | 'response',\n\t) {\n\t\tconst sourceText = source ? ` in ${source}` : '';\n\t\tsuper(`Schema validation failed${sourceText}`);\n\t\tthis.name = 'SchemaValidationError';\n\t\tthis.status = 400;\n\t}\n}\n\nexport class ApiError extends ErrorWithStatus {\n\tconstructor(message: string, status?: number) {\n\t\tsuper(message);\n\t\tthis.name = 'ApiError';\n\t\tthis.status = status ?? 500;\n\t}\n}\n\nexport class JsonParsingError extends ErrorWithStatus {\n\tconstructor(public response?: Response) {\n\t\tsuper('Error parsing response into JSON.');\n\t\tthis.name = 'ParsingError';\n\t\tthis.status = 500;\n\t}\n}\n\n/** @deprecated - use `JsonParsingError` instead */\nexport class ParsingError extends JsonParsingError {}\n\nexport type ApiClient = {\n\tfetch: (pathname: string, options?: RequestInit) => Promise<unknown>;\n};\n\nconst ERROR_MESSAGE_KEYS = ['message', 'error', 'errors', 'exception', 'exceptions'] as const;\nfunction getErrorMessageFromJson(json: unknown): string {\n\tconsole.log('json', json);\n\tconst messages: string[] = [];\n\tif (typeof json === 'object' && json !== null) {\n\t\tfor (const key of ERROR_MESSAGE_KEYS) {\n\t\t\tif (hasProp(json, key)) {\n\t\t\t\tconsole.log('hasProp', key, json[key]);\n\t\t\t\tconst value = json[key];\n\t\t\t\tif (typeof value === 'string') messages.push(value);\n\t\t\t\tif (Array.isArray(value) && value.every((item): item is string => typeof item === 'string'))\n\t\t\t\t\tmessages.push(...value);\n\t\t\t}\n\t\t}\n\t}\n\tif (messages.length === 0) messages.push('Unknown error');\n\treturn messages.join(', ');\n}\n\n/** Throws branded errors when API returns a known error. */\nexport function handleApiExceptions(json: unknown, status: number) {\n\tif (status >= 300 && status <= 500) {\n\t\tconst message = getErrorMessageFromJson(json);\n\t\tif (status === 404) {\n\t\t\tthrow new NotFoundError(message);\n\t\t}\n\t\tif (message === unauthenticatedMessage) {\n\t\t\tthrow new UnauthorisedError('You are not authenticated.', status);\n\t\t}\n\t\tif (message === unauthorisedMessage) {\n\t\t\tthrow new UnauthorisedError(message, status);\n\t\t}\n\t\tthrow new ApiError(message, status);\n\t}\n}\n\nexport const createApiClient = (params: { baseUrl: string; publishableKey: string }): ApiClient => {\n\tconst defaultHeaders: HeadersInit = {\n\t\tAccept: 'application/json',\n\t\t'Content-Type': 'application/json',\n\t\t'x-publishable-key': params.publishableKey,\n\t};\n\n\treturn {\n\t\t/** Fetches from a pathname with a pre-established base path.\n\t\t * Parses received output as JSON, and throw if one of the common error messages is received.\n\t\t */\n\t\tfetch: async (pathname, options = {}) => {\n\t\t\tconst init = { ...options, headers: { ...options.headers, ...defaultHeaders } };\n\t\t\tconst response = await fetch(`${params.baseUrl}${pathname}`, init);\n\t\t\tif (response.status === 404) throw new NotFoundError();\n\n\t\t\tconst json = await response.json().catch(async () => {\n\t\t\t\tthrow new JsonParsingError(response);\n\t\t\t});\n\n\t\t\thandleApiExceptions(json, response.status);\n\n\t\t\t// We’re assuming no other exceptions have happened.\n\t\t\treturn json;\n\t\t},\n\t};\n};\n\nexport const SdkError = {\n\tNotFound: NotFoundError,\n\tUnauthorised: UnauthorisedError,\n\tSchemaValidation: SchemaValidationError,\n\tApi: ApiError,\n\tJsonParsing: JsonParsingError,\n};\n\nexport function isSdkError(error: unknown): error is (typeof SdkError)[keyof typeof SdkError] {\n\treturn Object.values(SdkError).some(ErrorClass => error instanceof ErrorClass);\n}\n","{\n\t\"name\": \"@inploi/sdk\",\n\t\"version\": \"1.17.2\",\n\t\"main\": \"dist/index.js\",\n\t\"types\": \"dist/index.d.ts\",\n\t\"license\": \"MIT\",\n\t\"files\": [\n\t\t\"/dist\",\n\t\t\"/cdn\"\n\t],\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"require\": \"./dist/index.js\",\n\t\t\t\"import\": \"./dist/index.mjs\",\n\t\t\t\"types\": \"./dist/index.d.ts\"\n\t\t}\n\t},\n\t\"scripts\": {\n\t\t\"build:npm\": \"tsup --dts --dts-resolve\",\n\t\t\"build:cdn\": \"tsup --config tsup.cdn.config.ts\",\n\t\t\"build\": \"concurrently 'pnpm run build:npm' 'pnpm run build:cdn'\",\n\t\t\"dev\": \"tsup --watch --config tsup.cdn.config.ts\",\n\t\t\"check\": \"eslint src --fix --max-warnings 0 && tsc\",\n\t\t\"test\": \"bun test\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@happy-dom/global-registrator\": \"^13.6.2\",\n\t\t\"@inploi/core\": \"workspace:*\",\n\t\t\"@total-typescript/ts-reset\": \"^0.5.1\",\n\t\t\"@types/bun\": \"^1.2.5\",\n\t\t\"@types/react\": \"^18.2.33\",\n\t\t\"@types/react-dom\": \"^18.2.14\",\n\t\t\"autoprefixer\": \"^10.4.16\",\n\t\t\"concurrently\": \"9.1.2\",\n\t\t\"eslint\": \"^7.32.0\",\n\t\t\"eslint-config-custom\": \"workspace:*\",\n\t\t\"happy-dom\": \"^12.6.0\",\n\t\t\"ts-toolbelt\": \"^9.6.0\",\n\t\t\"tsconfig\": \"workspace:*\",\n\t\t\"tsup\": \"^7.2.0\"\n\t},\n\t\"dependencies\": {\n\t\t\"@standard-schema/spec\": \"^1.0.0\",\n\t\t\"neoqs\": \"^6.13.0\"\n\t}\n}\n","import { version } from '../package.json';\n\n/**\n * The environment the SDK should run in.\n * - `production`: data will be stored and displayed on dashboards\n * - `sandbox`: data will be stored temporarily and purged periodically\n */\nexport type InploiSdkEnvironment = 'production' | 'sandbox';\n\nexport const ENV_TO_API_URL: Record<InploiSdkEnvironment, string> = {\n\tsandbox: 'https://api.staging.inploi.com',\n\tproduction: 'https://api.inploi.com',\n\t// @ts-expect-error - local test environment\n\t_internal_local: 'http://api.test',\n};\n\nexport const ANALYTICS_VERSION = version;\n\nexport const LOG_PATHNAME = '/log';\n\nexport const ANALYTICS_COOKIE_NAME = 'isdk_session';\n","/**\n * Generates a RFC 4122 v4 UUID.\n *\n * `crypto.randomUUID()` is only available in secure contexts (HTTPS). This\n * utility falls back to `crypto.getRandomValues`, which is available in all\n * browsing contexts including HTTP, so the SDK works on non-HTTPS staging\n * environments.\n */\nexport const generateUUID = (): `${string}-${string}-${string}-${string}-${string}` => {\n\tif (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n\t\treturn crypto.randomUUID();\n\t}\n\n\treturn '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, c =>\n\t\t(+c ^ (crypto.getRandomValues(new Uint8Array(1))[0]! & (15 >> (+c / 4)))).toString(16),\n\t) as `${string}-${string}-${string}-${string}-${string}`;\n};\n","import type { ResponseObj } from '@inploi/core/common';\nimport { invariant } from '@inploi/core/common';\n\nimport { InploiRpcClient, Logger, endpoint, typed } from '.';\nimport { ANALYTICS_COOKIE_NAME, ANALYTICS_VERSION } from './sdk.constants';\nimport { generateUUID } from './sdk.uuid';\n\nconst formatCookie = (value: string) => {\n\tconst now = new Date();\n\tnow.setTime(now.getTime() + 7 * 24 * 60 * 60 * 1000); // 7 days expiration\n\n\treturn `${ANALYTICS_COOKIE_NAME}=${value};expires=${now.toUTCString()};path=/`;\n};\n\ntype FlowProperties = { flow_id: string; flow_version: number; flow_session_id: string; flow_build: number };\n\ntype JobProperties = {\n\tid: string;\n\tid_type: 'internal' | 'external';\n};\n\nexport type AnalyticsLogParams =\n\t| {\n\t\t\tevent: 'VIEW_JOB';\n\t\t\tproperties: { job: JobProperties };\n\t }\n\t| {\n\t\t\tevent: 'FLOW_REDIRECT';\n\t\t\tproperties: { href: string; job: JobProperties | undefined } & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'FLOW_START' | 'FLOW_END';\n\t\t\tproperties: { job: JobProperties | undefined } & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'FLOW_SUBMIT';\n\t\t\tproperties: {\n\t\t\t\tservice: string;\n\t\t\t\tresponse: {\n\t\t\t\t\tstatus: number;\n\t\t\t\t\tpayload: unknown;\n\t\t\t\t};\n\t\t\t\tjob: JobProperties | undefined;\n\t\t\t} & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'SUBMIT_FORM' | 'VIEW_PAGE';\n\t\t\tproperties?: {\n\t\t\t\tjob: JobProperties | undefined;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'IDENTIFY';\n\t\t\tproperties: {\n\t\t\t\tidentifier: string;\n\t\t\t\tfirst_name?: string;\n\t\t\t\tlast_name?: string;\n\t\t\t\tphone_number?: string;\n\t\t\t\temail?: string;\n\t\t\t\tcustom_traits?: Record<string, unknown>;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_PAGINATE';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_SETTLE';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_JOB_CLICK';\n\t\t\tproperties: {\n\t\t\t\tjob_id: number;\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'VIEW_SEARCH';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'FEEDBACK';\n\t\t\tproperties: {\n\t\t\t\tkey: string;\n\t\t\t\tscore?: -1 | 0 | 1;\n\t\t\t\tcomment?: string;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'LINK_CLICK';\n\t\t\tproperties: {\n\t\t\t\ttarget_href: string;\n\t\t\t\tjob_id: string | undefined;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'INTERACTION';\n\t\t\tproperties: {\n\t\t\t\ttag: string;\n\t\t\t};\n\t };\n\nexport type AnalyticsLogEvent = AnalyticsLogParams['event'];\n\ntype EventPropertyMap = {\n\t[Param in AnalyticsLogParams as Param['event']]: Omit<Param, 'event'>;\n};\n\ntype AnalyticsContext = {\n\tlibrary: {\n\t\tname: 'inploi-sdk';\n\t\tversion: string;\n\t};\n\tpage: {\n\t\thref: string;\n\t\treferrer: string;\n\t\ttitle: string;\n\t};\n};\n\ntype TrackPayload<P = EventPropertyMap[keyof EventPropertyMap]['properties']> = {\n\tanonymous_id: string | null;\n\tsession_id: string | null;\n\tevent: AnalyticsLogEvent;\n\tsent_at: string;\n\tcontext: AnalyticsContext;\n\tproperties: P;\n\tcustom_properties?: Record<string, unknown>;\n};\n\ntype LogFnParams<T extends keyof EventPropertyMap> = {\n\tevent: T;\n\tcustomProperties?: Record<string, unknown>;\n\t/** Passing a request will make logging possible on a server environment. */\n\trequest?: Request;\n} & EventPropertyMap[T];\n\ntype LogFn = <TEvent extends keyof EventPropertyMap>(\n\tparams: LogFnParams<TEvent>,\n) => Promise<ResponseObj<TrackPayload<EventPropertyMap[TEvent]['properties']>>>;\n\nexport type AnalyticsService = {\n\tlog: LogFn;\n\t/** From a log payload data, generate headers to use in server environments to update the anonymous_id */\n\tgetHeaders: (payload?: TrackPayload) => Headers;\n\tgetSessionInfo: typeof getSessionInfo;\n};\n\nconst getSessionId = (searchParams: URLSearchParams, isServer: boolean) => {\n\tconst fromSearchParams = searchParams.get('session_id');\n\tif (isServer) return fromSearchParams;\n\tif (fromSearchParams) return fromSearchParams;\n\tconst fromSessionStorage = sessionStorage.getItem(`${ANALYTICS_COOKIE_NAME}-session_id`);\n\tif (typeof fromSessionStorage === 'string') return fromSessionStorage;\n\treturn null;\n};\n\nconst cookieRegex = new RegExp(`${ANALYTICS_COOKIE_NAME}=([^;]+)`);\nconst getSessionInfo = (request?: Request) => {\n\tconst href = request ? request.url : location.href;\n\tconst { searchParams } = new URL(href);\n\tconst anonymous_id = searchParams.get('anonymous_id');\n\tconst session_id = getSessionId(searchParams, typeof window === 'undefined');\n\n\t// If there's an anonymous_id in the search params, use it\n\tif (anonymous_id)\n\t\treturn {\n\t\t\tanonymous_id,\n\t\t\tsession_id,\n\t\t};\n\n\t// If there's a cookie, use it\n\tconst cookie = request ? request.headers.get('cookie') : document.cookie;\n\tif (cookie) {\n\t\tconst match = cookieRegex.exec(cookie);\n\t\tconst anonymous_id = match?.[1];\n\t\treturn {\n\t\t\tanonymous_id: anonymous_id ?? null,\n\t\t\tsession_id,\n\t\t};\n\t}\n\n\t// Otherwise, return what we have\n\treturn {\n\t\tanonymous_id,\n\t\tsession_id,\n\t};\n};\n\n/**\n * Get or create a persistent anonymous ID.\n *\n * This is the universal identifier that bridges:\n * - SDK analytics (Laravel tracking)\n * - Agent conversations (Durable Object routing)\n * - Identity resolution\n *\n * The ID is:\n * - Generated client-side if none exists\n * - Persisted in cookie for 7 days\n * - The same across all SDK plugins\n *\n * @returns The anonymous ID (existing or newly generated)\n */\nexport const getOrCreateAnonymousId = (): string => {\n\t// Server-side: cannot generate, return empty (should not happen in normal flow)\n\tif (typeof window === 'undefined') {\n\t\tthrow new Error('getOrCreateAnonymousId() can only be called in browser environment');\n\t}\n\n\t// Check existing sources first\n\tconst existing = getSessionInfo().anonymous_id;\n\tif (existing) return existing;\n\n\t// Generate new ID and immediately persist to cookie\n\tconst newId = generateUUID();\n\tdocument.cookie = formatCookie(newId);\n\treturn newId;\n};\n\nconst getSessionInfoFromResponse = (response: unknown) => {\n\tif (typeof response !== 'object' || response === null) return null;\n\treturn {\n\t\tanonymous_id:\n\t\t\t'anonymous_id' in response && typeof response.anonymous_id === 'string' ? response.anonymous_id : null,\n\t\tsession_id: 'session_id' in response && typeof response.session_id === 'string' ? response.session_id : null,\n\t};\n};\n\nconst serverReferrer = (referrer: typeof Request.prototype.referrer) => {\n\tif (referrer === 'about:client') return '';\n\treturn referrer;\n};\n\nconst analyticsLogEndpoint = endpoint({\n\tpathname: '/log',\n\tmethod: 'POST',\n\tschema: {\n\t\tresponse: typed<unknown>(),\n\t\tbody: typed<TrackPayload>(),\n\t},\n});\n\nexport type AnalyticsOnEventCallback = (event: AnalyticsLogParams) => void;\n\nexport const createAnalyticsService = ({\n\trpcClient,\n\tlogger,\n\tonEvent,\n}: {\n\tlogger: Logger;\n\trpcClient: InploiRpcClient;\n\tonEvent?: AnalyticsOnEventCallback;\n}): AnalyticsService => {\n\tconst logFn: LogFn = async params => {\n\t\tinvariant(\n\t\t\tparams.request || typeof window !== 'undefined',\n\t\t\t'Cannot log on the server without a request. Please pass a request to `log`.',\n\t\t);\n\n\t\t// if there’s a request, use it instead of browser APIs\n\t\tconst page =\n\t\t\t'request' in params && params.request ?\n\t\t\t\t{\n\t\t\t\t\thref: params.request.url,\n\t\t\t\t\treferrer: serverReferrer(params.request.referrer),\n\t\t\t\t\ttitle: '',\n\t\t\t\t}\n\t\t\t:\t{\n\t\t\t\t\thref: location.href,\n\t\t\t\t\treferrer: document.referrer,\n\t\t\t\t\ttitle: document.title,\n\t\t\t\t};\n\n\t\ttry {\n\t\t\tconst context: AnalyticsContext = {\n\t\t\t\tlibrary: {\n\t\t\t\t\tname: 'inploi-sdk',\n\t\t\t\t\tversion: ANALYTICS_VERSION,\n\t\t\t\t},\n\t\t\t\tpage,\n\t\t\t};\n\n\t\t\tconst sessionInfo = getSessionInfo(params.request);\n\t\t\tconst payload: TrackPayload = {\n\t\t\t\tanonymous_id: sessionInfo.anonymous_id,\n\t\t\t\tsession_id: sessionInfo.session_id,\n\t\t\t\tevent: params.event,\n\t\t\t\tsent_at: new Date().toISOString(),\n\t\t\t\tcontext,\n\t\t\t\tproperties: params.properties,\n\t\t\t\tcustom_properties: params.customProperties,\n\t\t\t};\n\n\t\t\tconst responseJson = await rpcClient.request(analyticsLogEndpoint, {\n\t\t\t\tbody: payload,\n\t\t\t});\n\n\t\t\tconst newSession = getSessionInfoFromResponse(responseJson);\n\t\t\tif (newSession?.anonymous_id) {\n\t\t\t\tpayload.anonymous_id = newSession.anonymous_id;\n\t\t\t}\n\t\t\tif (newSession?.session_id) {\n\t\t\t\tpayload.session_id = newSession.session_id;\n\t\t\t}\n\n\t\t\tif (typeof window !== 'undefined' && payload.anonymous_id) {\n\t\t\t\tif (payload.session_id) {\n\t\t\t\t\tsessionStorage.setItem(`${ANALYTICS_COOKIE_NAME}-session_id`, payload.session_id.toString());\n\t\t\t\t}\n\t\t\t\tdocument.cookie = formatCookie(payload.anonymous_id);\n\t\t\t}\n\n\t\t\tonEvent?.(payload as AnalyticsLogParams);\n\t\t\treturn { success: true, data: payload };\n\t\t} catch (e) {\n\t\t\t/** We dont’t log any PII on the console */\n\t\t\tlogger.error('Failed to send log to API. Inspect error response of `log` for more information.');\n\t\t\treturn { success: false, error: e };\n\t\t}\n\t};\n\n\treturn {\n\t\tlog: logFn,\n\t\tgetHeaders: payload => {\n\t\t\tconst headers = new Headers();\n\t\t\tif (!payload?.anonymous_id) return headers;\n\n\t\t\theaders.append('Set-Cookie', formatCookie(payload.anonymous_id));\n\t\t\treturn headers;\n\t\t},\n\t\tgetSessionInfo,\n\t};\n};\n","import type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { stringify } from 'neoqs';\n\nimport { JsonParsingError, SchemaValidationError, handleApiExceptions } from './sdk.api';\nimport { ENV_TO_API_URL, InploiSdkEnvironment } from './sdk.constants';\nimport { Logger } from './sdk.logger';\n\ntype RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\n\n/** Extract parameter names from a pathname string */\ntype ExtractParamNames<T extends string> =\n\tT extends `${infer _Before}:${infer Param}/${infer After}` ? Param | ExtractParamNames<`/${After}`>\n\t: T extends `${infer _Before}:${infer Param}` ? Param\n\t: never;\n\n/** Create params object from parameter names */\ntype ExtractPathParams<T extends string> =\n\tstring extends T ? Record<string, string | number>\n\t: ExtractParamNames<T> extends never ? Record<string, never>\n\t: { [K in ExtractParamNames<T>]: string | number };\n\n/** Parses a StandardSchemaV1 schema and input into an output. */\nexport function parse<T extends StandardSchemaV1>(\n\tschema: T,\n\tinput: StandardSchemaV1.InferInput<T>,\n\tsource?: 'body' | 'searchParams' | 'response',\n): StandardSchemaV1.InferOutput<T> {\n\tconst result = schema['~standard'].validate(input);\n\tif (result instanceof Promise) {\n\t\tthrow new TypeError('Async schema');\n\t}\n\n\tif (result.issues) {\n\t\tthrow new SchemaValidationError(result.issues, source);\n\t}\n\n\treturn result.value;\n}\n\n/** Parses a StandardSchemaV1 schema and input into an output, returning a success flag and issues if the parse fails. */\nexport function safeParse<T extends StandardSchemaV1>(\n\tschema: T,\n\tinput: StandardSchemaV1.InferInput<T>,\n\tsource?: 'body' | 'searchParams' | 'response',\n):\n\t| {\n\t\t\tsuccess: true;\n\t\t\toutput: StandardSchemaV1.InferOutput<T>;\n\t }\n\t| {\n\t\t\tsuccess: false;\n\t\t\tissues: readonly StandardSchemaV1.Issue[];\n\t\t\tsource?: 'body' | 'searchParams' | 'response';\n\t } {\n\ttry {\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\toutput: parse(schema, input, source),\n\t\t};\n\t} catch (e) {\n\t\tif (e instanceof SchemaValidationError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tissues: e.issues,\n\t\t\t\tsource: e.source,\n\t\t\t};\n\t\t}\n\t\tthrow e;\n\t}\n}\n\nexport interface InploiRpcClientParams {\n\tenvironment: InploiSdkEnvironment;\n\tlogger: Logger;\n\tapiKey:\n\t\t| {\n\t\t\t\t/** Makes the API call with an x-secret-key header\n\t\t\t\t * This will error if used in a browser environment.\n\t\t\t\t */\n\t\t\t\ttype: 'secret';\n\t\t\t\tkey: string;\n\t\t }\n\t\t| {\n\t\t\t\t/** Makes the API call with an x-publishable-key header\n\t\t\t\t * This can be called in a browser or server environment.\n\t\t\t\t */\n\t\t\t\ttype: 'publishable';\n\t\t\t\tkey: string;\n\t\t };\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\ntype NonReducibleUnknown = {} | null | undefined;\ntype LooseAutocomplete<T extends BaseType, BaseType> = T | BaseType;\n\n/** RPC client for making API calls to the Inploi API. */\nexport class InploiRpcClient {\n\tprivate baseUrl: string;\n\tprivate headers: Headers;\n\tprivate logger: Logger;\n\tprivate _environment: InploiSdkEnvironment;\n\n\tconstructor(params: InploiRpcClientParams) {\n\t\tthis.baseUrl = ENV_TO_API_URL[params.environment];\n\t\tthis.headers = new Headers({\n\t\t\t'Content-Type': 'application/json',\n\t\t\tAccept: 'application/json',\n\t\t});\n\t\tif (params.apiKey.type === 'secret') {\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\tthrow new Error('Secret key cannot be used in a browser environment');\n\t\t\t}\n\t\t\tthis.headers.set('x-secret-key', params.apiKey.key);\n\t\t} else {\n\t\t\tthis.headers.set('x-publishable-key', params.apiKey.key);\n\t\t}\n\t\tthis.logger = params.logger;\n\t\tthis._environment = params.environment;\n\t}\n\n\tget environment() {\n\t\treturn this._environment;\n\t}\n\n\t/** Gets params for a fetch request to the given endpoint */\n\tgetFetchParams<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: T extends RpcEndpoint<infer _, infer _TPathname, infer TPathParams, infer TSearch, infer TBody> ?\n\t\t\tGetSchemaValues<{\n\t\t\t\tbody: TBody;\n\t\t\t\tsearchParams: TSearch;\n\t\t\t\tparams: TPathParams;\n\t\t\t}> & {\n\t\t\t\tsignal?: AbortSignal;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the inputs against the schema.\n\t\t\t\t * If you want to skip validation (e.g.: already validated yourself or with `validateEndpontInputs`), set this to false.\n\t\t\t\t */\n\t\t\t\tvalidateIn?: boolean;\n\t\t\t}\n\t\t:\tnever,\n\t): [url: string, options: RequestInit] {\n\t\tconst validateIn = options.validateIn ?? true;\n\t\tconst { searchParams, body } = validateIn ? validateEndpointInputs(endpoint, options) : options;\n\n\t\tconst url = new URL(this.baseUrl);\n\n\t\t// Replace path parameters in pathname\n\t\tlet pathname = endpoint.pathname;\n\t\tif ('params' in options && options.params) {\n\t\t\tfor (const [key, value] of Object.entries(options.params)) {\n\t\t\t\tpathname = pathname.replace(`:${key}`, String(value));\n\t\t\t}\n\t\t}\n\t\turl.pathname = pathname;\n\n\t\tif (endpoint.schema.searchParams) {\n\t\t\turl.search = stringify(searchParams);\n\t\t}\n\n\t\treturn [\n\t\t\turl.toString(),\n\t\t\t{\n\t\t\t\tmethod: endpoint.method,\n\t\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t\t\theaders: this.headers,\n\t\t\t\tsignal: options.signal,\n\t\t\t},\n\t\t];\n\t}\n\n\t/** Parses a response against an endpoint’s response schema, considering common errors thrown from the API.\n\t * @throws {JsonParsingError} - If the response is not valid JSON.\n\t * @throws {SchemaValidationError} - If the response does not match the schema.\n\t * @throws {ApiError} - If the API responded with an error message.\n\t */\n\tasync parseResponse<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: {\n\t\t\tresponse: Response;\n\t\t\t/**\n\t\t\t * Whether to validate the response against the schema.\n\t\t\t * This is meant more as an escape hatch for when the response is not as expected and you want to handle it separately yourself.\n\t\t\t * ⚠️ This will lead to potential type/runtime mismatch as it does not verify the response against the schema.\n\t\t\t */\n\t\t\tvalidateOut?: boolean;\n\t\t},\n\t): Promise<StandardSchemaV1.InferOutput<T['schema']['response']>> {\n\t\tconst json = await options.response.json().catch(e => {\n\t\t\tthis.logger.error(e);\n\t\t\tthrow new JsonParsingError(options.response);\n\t\t});\n\n\t\tconst validateOut = options.validateOut ?? true;\n\t\tif (!validateOut) return json as StandardSchemaV1.InferOutput<T['schema']['response']>;\n\n\t\tconst result = safeParse(endpoint.schema.response, json, 'response');\n\t\tif (!result.success) {\n\t\t\thandleApiExceptions(json, options.response.status);\n\t\t\tthrow new SchemaValidationError(result.issues, result.source);\n\t\t}\n\n\t\treturn result.output as StandardSchemaV1.InferOutput<T['schema']['response']>;\n\t}\n\n\t/** Fetches, parses and validates an API endpoint.\n\t * Logs errors and throws them again so that the caller can handle them.\n\t *\n\t * @throws {JsonParsingError} - If the response is not valid JSON.\n\t * @throws {SchemaValidationError} - If the searchParams, body or response does not match the schema.\n\t * @throws {ApiError} - If the API responded with an error message.\n\t * @throws {UnauthorisedError} - If the request is unauthorised either by missing key or unmet permissions.\n\t * @throws {NotFoundError} - If the endpoint is not found.\n\t * @throws {Error} - Another unhandled error.\n\t */\n\tasync request<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: T extends RpcEndpoint<infer _, infer _TPathname, infer TPathParams, infer TSearch, infer TBody> ?\n\t\t\tGetSchemaValues<{\n\t\t\t\tbody: TBody;\n\t\t\t\tsearchParams: TSearch;\n\t\t\t\tparams: TPathParams;\n\t\t\t}> & {\n\t\t\t\tsignal?: AbortSignal;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the inputs against the schema.\n\t\t\t\t * If you want to skip validation (e.g.: already validated yourself or with `validateEndpontInputs`), set this to false.\n\t\t\t\t */\n\t\t\t\tvalidateIn?: boolean;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the response against the schema.\n\t\t\t\t * This is meant more as an escape hatch for when the response is not as expected and you want to handle it separately yourself.\n\t\t\t\t * ⚠️ This will lead to potential type/runtime mismatch as it does not verify the response against the schema.\n\t\t\t\t */\n\t\t\t\tvalidateOut?: boolean;\n\t\t\t}\n\t\t:\tnever,\n\t): Promise<StandardSchemaV1.InferOutput<T['schema']['response']>> {\n\t\ttry {\n\t\t\tconst fetchParams = this.getFetchParams(endpoint, options);\n\t\t\tconst response = await fetch(...fetchParams);\n\t\t\treturn this.parseResponse(endpoint, { response, validateOut: options.validateOut });\n\t\t} catch (e) {\n\t\t\tif (e instanceof SchemaValidationError) {\n\t\t\t\tthis.logger.error(e.message, e.issues);\n\t\t\t} else {\n\t\t\t\tthis.logger.error(e);\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t}\n}\n\ntype GetSchemaValues<T extends { searchParams: any; body: any; params?: any }> = {\n\t[K in keyof T as T[K] extends never ? never\n\t: T[K] extends Record<string, never> ? never\n\t: K]: T[K] extends never ? never : LooseAutocomplete<T[K], NonReducibleUnknown>;\n};\n\n/**\n * Typed but *not runtime validated* schema\n * useful for type-checking the schema without bundling validation schemas\n */\nexport function typed<T>(): StandardSchemaV1<T, T> {\n\treturn {\n\t\t'~standard': {\n\t\t\tvendor: 'inploi',\n\t\t\tversion: 1,\n\t\t\tvalidate: input => {\n\t\t\t\treturn {\n\t\t\t\t\tvalue: input as T,\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t};\n}\n\nexport interface RpcEndpoint<\n\tTMethod extends RequestMethod = RequestMethod,\n\tTPathname extends string = string,\n\tTPathParams = any,\n\tTSearch = any,\n\tTBody = any,\n\tTResponse = any,\n> {\n\tpathname: TPathname;\n\tmethod: TMethod;\n\theaders?: Headers;\n\tschema: {\n\t\tsearchParams?: StandardSchemaV1<TSearch, TSearch>;\n\t\tbody?: StandardSchemaV1<TBody, TBody>;\n\t\tresponse: StandardSchemaV1<TResponse, TResponse>;\n\t};\n\t/** Type-only property to store path parameter types */\n\treadonly __pathParams?: TPathParams;\n}\n\nexport function endpoint<\n\tTMethod extends RequestMethod,\n\tTPathname extends string,\n\tTSearch extends StandardSchemaV1 | never = never,\n\tTBody extends StandardSchemaV1 | never = never,\n\tTResponse extends StandardSchemaV1 | never = never,\n>(endpoint: {\n\tpathname: TPathname;\n\tmethod: TMethod;\n\theaders?: Headers;\n\tschema: {\n\t\tsearchParams?: TSearch;\n\t\tbody?: TBody;\n\t\tresponse: TResponse;\n\t};\n}) {\n\ttype PathParams = ExtractPathParams<TPathname>;\n\treturn endpoint as RpcEndpoint<\n\t\tTMethod,\n\t\tTPathname,\n\t\tPathParams,\n\t\tStandardSchemaV1.InferInput<TSearch>,\n\t\tStandardSchemaV1.InferInput<TBody>,\n\t\tStandardSchemaV1.InferOutput<TResponse>\n\t>;\n}\n\n/** Validates the inputs for an endpoint ahead of time\n * Useful when you need to validate and throw earlier, or use the inputs for something other than the API call.\n */\nexport function validateEndpointInputs<T extends RpcEndpoint>(\n\tendpoint: T,\n\toptions: GetSchemaValues<{ body: unknown; searchParams: unknown }>,\n) {\n\tconst validatedInputs = {\n\t\tsearchParams: undefined,\n\t\tbody: undefined,\n\t\tvalidateIn: false,\n\t} as T extends RpcEndpoint<infer _, infer __, infer ___, infer TSearch, infer TBody> ?\n\t\tGetSchemaValues<{\n\t\t\tbody: TBody;\n\t\t\tsearchParams: TSearch;\n\t\t}> & {\n\t\t\tvalidateIn: false;\n\t\t}\n\t:\tnever;\n\n\tif (endpoint.schema.searchParams) {\n\t\tvalidatedInputs.searchParams = parse(\n\t\t\tendpoint.schema.searchParams,\n\t\t\t'searchParams' in options ? options.searchParams : {},\n\t\t);\n\t}\n\n\tif (endpoint.schema.body) {\n\t\tvalidatedInputs.body = parse(endpoint.schema.body, 'body' in options ? options.body : {});\n\t}\n\n\treturn validatedInputs;\n}\n","import { AnalyticsOnEventCallback, createAnalyticsService } from './sdk.analytics';\nimport { createApiClient } from './sdk.api';\nimport { ENV_TO_API_URL, InploiSdkEnvironment } from './sdk.constants';\nimport { Logger, inploiBrandedLogger, noLogging } from './sdk.logger';\nimport { InploiSdkPlugin } from './sdk.plugins';\nimport { InploiRpcClient } from './sdk.rpc';\n\nexport type InitialiseInploiSdkParams = {\n\t/** Your public API key for the inploi SDK. */\n\tpublishableKey: string;\n\t/** Which app environment to run. This ultimately affects which inploi endpoints to gather data are going to be used.\n\t * Anything other than `production` should be considered a development environment and the data periodicaly purged. */\n\tenv: InploiSdkEnvironment;\n\t/** Logger object that handles logging of different levels.\n\t * You can override this to use your own logger, or to disable logging altogether by passing`false`.\n\t * @default inploiBrandedLogger\n\t * */\n\tlogger?: Logger | false;\n\n\t/** When provided, this callback will be called with every event that is logged to the analytics service. */\n\tonEvent?: AnalyticsOnEventCallback;\n};\n\nexport function initialiseSdk({\n\tpublishableKey,\n\tenv,\n\tlogger = inploiBrandedLogger,\n\tonEvent,\n}: InitialiseInploiSdkParams) {\n\t/** @deprecated - use `rpcClient` instead */\n\tconst apiClient = createApiClient({ baseUrl: ENV_TO_API_URL[env], publishableKey });\n\tconst loggerService = logger === false ? noLogging : logger;\n\tconst rpcClient = new InploiRpcClient({\n\t\tenvironment: env,\n\t\tapiKey: { type: 'publishable', key: publishableKey },\n\t\tlogger: loggerService,\n\t});\n\tconst analytics = createAnalyticsService({ rpcClient, logger: loggerService, onEvent });\n\n\tconst register = <P extends InploiSdkPlugin>(plugin: P): ReturnType<P> => {\n\t\treturn plugin({ logger: loggerService, apiClient, analytics, rpcClient, publishableKey, env });\n\t};\n\n\treturn { register, analytics, apiClient };\n}\n\nexport type InploiSdk = ReturnType<typeof initialiseSdk>;\n"],"mappings":"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","names":["src_exports","__export","ApiError","InploiRpcClient","NotFoundError","JsonParsingError","SchemaValidationError","SdkError","UnauthorisedError","createPlugin","endpoint","generateUUID","getOrCreateAnonymousId","initialiseSdk","inploiBrandedLogger","isSdkError","noLogging","typed","validateEndpointInputs","__toCommonJS","CONSOLE_PREFIX","CONSOLE_STYLE","inploiBrandedLogger","args","noLogging","createPlugin","pluginFn","invariant","condition","message","hasProp","data","prop","DEFAULT_FORMATTER","unauthenticatedMessage","unauthorisedMessage","ErrorWithStatus","message","status","NotFoundError","UnauthorisedError","SchemaValidationError","issues","source","sourceText","ApiError","JsonParsingError","response","ERROR_MESSAGE_KEYS","getErrorMessageFromJson","json","messages","key","hasProp","value","item","handleApiExceptions","status","message","NotFoundError","unauthenticatedMessage","UnauthorisedError","unauthorisedMessage","ApiError","createApiClient","params","defaultHeaders","pathname","options","init","response","JsonParsingError","SdkError","SchemaValidationError","isSdkError","error","ErrorClass","version","ENV_TO_API_URL","ANALYTICS_VERSION","version","ANALYTICS_COOKIE_NAME","generateUUID","c","formatCookie","value","now","ANALYTICS_COOKIE_NAME","getSessionId","searchParams","isServer","fromSearchParams","fromSessionStorage","cookieRegex","getSessionInfo","request","href","anonymous_id","session_id","cookie","getOrCreateAnonymousId","existing","newId","generateUUID","getSessionInfoFromResponse","response","serverReferrer","referrer","analyticsLogEndpoint","typed","createAnalyticsService","rpcClient","logger","onEvent","params","invariant","page","context","ANALYTICS_VERSION","sessionInfo","payload","responseJson","newSession","e","headers","import_neoqs","parse","schema","input","source","result","SchemaValidationError","safeParse","e","InploiRpcClient","params","ENV_TO_API_URL","endpoint","options","validateIn","searchParams","body","validateEndpointInputs","url","pathname","key","value","json","JsonParsingError","handleApiExceptions","fetchParams","response","typed","validatedInputs","initialiseSdk","publishableKey","env","logger","inploiBrandedLogger","onEvent","apiClient","createApiClient","ENV_TO_API_URL","loggerService","noLogging","rpcClient","InploiRpcClient","analytics","createAnalyticsService","plugin"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- var T="%c[inploi SDK]",S="color: #65BC67; font-weight: bold;",x={warn:(...e)=>console.warn(T,S,...e),error:(...e)=>console.error(T,S,...e),info:(...e)=>console.info(T,S,...e),log:(...e)=>console.log(T,S,...e)},b={info:()=>{},error:()=>{},log:()=>{},warn:()=>{}};var F=e=>e;function E(e,n){if(!e)throw new Error(n)}function w(e,n){return n in e}var pe=new Intl.RelativeTimeFormat(void 0,{numeric:"auto"});var q="Unauthenticated",U="This action is unauthorized.",d=class extends Error{constructor(r,t){super(r);this.status=t,this.name="ErrorWithStatus"}},l=class extends d{constructor(n){super(n??"Not found"),this.name="NotFoundError",this.status=404}},m=class extends d{constructor(n,r){super(n??"You are not authorised to perform this action."),this.name="UnauthorisedError",this.status=r??401}},c=class extends d{constructor(r,t){let o=t?` in ${t}`:"";super(`Schema validation failed${o}`);this.issues=r;this.source=t;this.name="SchemaValidationError",this.status=400}},y=class extends d{constructor(n,r){super(n),this.name="ApiError",this.status=r??500}},u=class extends d{constructor(r){super("Error parsing response into JSON.");this.response=r;this.name="ParsingError",this.status=500}};var j=["message","error","errors","exception","exceptions"];function K(e){console.log("json",e);let n=[];if(typeof e=="object"&&e!==null){for(let r of j)if(w(e,r)){console.log("hasProp",r,e[r]);let t=e[r];typeof t=="string"&&n.push(t),Array.isArray(t)&&t.every(o=>typeof o=="string")&&n.push(...t)}}return n.length===0&&n.push("Unknown error"),n.join(", ")}function I(e,n){if(n>=300&&n<=500){let r=K(e);throw n===404?new l(r):r===q?new m("You are not authenticated.",n):r===U?new m(r,n):new y(r,n)}}var L=e=>{let n={Accept:"application/json","Content-Type":"application/json","x-publishable-key":e.publishableKey};return{fetch:async(r,t={})=>{let o={...t,headers:{...t.headers,...n}},s=await fetch(`${e.baseUrl}${r}`,o);if(s.status===404)throw new l;let a=await s.json().catch(async()=>{throw new u(s)});return I(a,s.status),a}}},O={NotFound:l,Unauthorised:m,SchemaValidation:c,Api:y,JsonParsing:u};function $(e){return Object.values(O).some(n=>e instanceof n)}var C="1.17.0";var P={sandbox:"https://api.staging.inploi.com",production:"https://api.inploi.com",_internal_local:"http://api.test"},N=C;var f="isdk_session";var k=e=>{let n=new Date;return n.setTime(n.getTime()+7*24*60*60*1e3),`${f}=${e};expires=${n.toUTCString()};path=/`},H=(e,n)=>{let r=e.get("session_id");if(n||r)return r;let t=sessionStorage.getItem(`${f}-session_id`);return typeof t=="string"?t:null},J=new RegExp(`${f}=([^;]+)`),R=e=>{let n=e?e.url:location.href,{searchParams:r}=new URL(n),t=r.get("anonymous_id"),o=H(r,typeof window>"u");if(t)return{anonymous_id:t,session_id:o};let s=e?e.headers.get("cookie"):document.cookie;return s?{anonymous_id:J.exec(s)?.[1]??null,session_id:o}:{anonymous_id:t,session_id:o}},Y=()=>{if(typeof window>"u")throw new Error("getOrCreateAnonymousId() can only be called in browser environment");let e=R().anonymous_id;if(e)return e;let n=crypto.randomUUID();return document.cookie=k(n),n},G=e=>typeof e!="object"||e===null?null:{anonymous_id:"anonymous_id"in e&&typeof e.anonymous_id=="string"?e.anonymous_id:null,session_id:"session_id"in e&&typeof e.session_id=="string"?e.session_id:null},W=e=>e==="about:client"?"":e,z={pathname:"/log",method:"POST",schema:{response:_(),body:_()}},V=({rpcClient:e,logger:n,onEvent:r})=>({log:async o=>{E(o.request||typeof window<"u","Cannot log on the server without a request. Please pass a request to `log`.");let s="request"in o&&o.request?{href:o.request.url,referrer:W(o.request.referrer),title:""}:{href:location.href,referrer:document.referrer,title:document.title};try{let a={library:{name:"inploi-sdk",version:N},page:s},p=R(o.request),i={anonymous_id:p.anonymous_id,session_id:p.session_id,event:o.event,sent_at:new Date().toISOString(),context:a,properties:o.properties,custom_properties:o.customProperties},g=await e.request(z,{body:i}),v=G(g);return v?.anonymous_id&&(i.anonymous_id=v.anonymous_id),v?.session_id&&(i.session_id=v.session_id),typeof window<"u"&&i.anonymous_id&&(i.session_id&&sessionStorage.setItem(`${f}-session_id`,i.session_id.toString()),document.cookie=k(i.anonymous_id)),r?.(i),{success:!0,data:i}}catch(a){return n.error("Failed to send log to API. Inspect error response of `log` for more information."),{success:!1,error:a}}},getHeaders:o=>{let s=new Headers;return o?.anonymous_id&&s.append("Set-Cookie",k(o.anonymous_id)),s},getSessionInfo:R});import{stringify as X}from"neoqs";function A(e,n,r){let t=e["~standard"].validate(n);if(t instanceof Promise)throw new TypeError("Async schema");if(t.issues)throw new c(t.issues,r);return t.value}function Z(e,n,r){try{return{success:!0,output:A(e,n,r)}}catch(t){if(t instanceof c)return{success:!1,issues:t.issues,source:t.source};throw t}}var h=class{constructor(n){if(this.baseUrl=P[n.environment],this.headers=new Headers({"Content-Type":"application/json",Accept:"application/json"}),n.apiKey.type==="secret"){if(typeof window<"u")throw new Error("Secret key cannot be used in a browser environment");this.headers.set("x-secret-key",n.apiKey.key)}else this.headers.set("x-publishable-key",n.apiKey.key);this.logger=n.logger,this._environment=n.environment}get environment(){return this._environment}getFetchParams(n,r){let t=r.validateIn??!0,{searchParams:o,body:s}=t?B(n,r):r,a=new URL(this.baseUrl),p=n.pathname;if("params"in r&&r.params)for(let[i,g]of Object.entries(r.params))p=p.replace(`:${i}`,String(g));return a.pathname=p,n.schema.searchParams&&(a.search=X(o)),[a.toString(),{method:n.method,body:s?JSON.stringify(s):void 0,headers:this.headers,signal:r.signal}]}async parseResponse(n,r){let t=await r.response.json().catch(a=>{throw this.logger.error(a),new u(r.response)});if(!(r.validateOut??!0))return t;let s=Z(n.schema.response,t,"response");if(!s.success)throw I(t,r.response.status),new c(s.issues,s.source);return s.output}async request(n,r){try{let t=this.getFetchParams(n,r),o=await fetch(...t);return this.parseResponse(n,{response:o,validateOut:r.validateOut})}catch(t){throw t instanceof c?this.logger.error(t.message,t.issues):this.logger.error(t),t}}};function _(){return{"~standard":{vendor:"inploi",version:1,validate:e=>({value:e})}}}function M(e){return e}function B(e,n){let r={searchParams:void 0,body:void 0,validateIn:!1};return e.schema.searchParams&&(r.searchParams=A(e.schema.searchParams,"searchParams"in n?n.searchParams:{})),e.schema.body&&(r.body=A(e.schema.body,"body"in n?n.body:{})),r}function Q({publishableKey:e,env:n,logger:r=x,onEvent:t}){let o=L({baseUrl:P[n],publishableKey:e}),s=r===!1?b:r,a=new h({environment:n,apiKey:{type:"publishable",key:e},logger:s}),p=V({rpcClient:a,logger:s,onEvent:t});return{register:g=>g({logger:s,apiClient:o,analytics:p,rpcClient:a,publishableKey:e}),analytics:p,apiClient:o}}export{y as ApiError,h as InploiRpcClient,l as NotFoundError,u as ParsingError,c as SchemaValidationError,O as SdkError,m as UnauthorisedError,F as createPlugin,M as endpoint,Y as getOrCreateAnonymousId,Q as initialiseSdk,x as inploiBrandedLogger,$ as isSdkError,b as noLogging,_ as typed,B as validateEndpointInputs};
1
+ var S="%c[inploi SDK]",T="color: #65BC67; font-weight: bold;",x={warn:(...e)=>console.warn(S,T,...e),error:(...e)=>console.error(S,T,...e),info:(...e)=>console.info(S,T,...e),log:(...e)=>console.log(S,T,...e)},b={info:()=>{},error:()=>{},log:()=>{},warn:()=>{}};var B=e=>e;function E(e,n){if(!e)throw new Error(n)}function I(e,n){return n in e}var ce=new Intl.RelativeTimeFormat(void 0,{numeric:"auto"});var F="Unauthenticated",q="This action is unauthorized.",d=class extends Error{constructor(r,t){super(r);this.status=t,this.name="ErrorWithStatus"}},l=class extends d{constructor(n){super(n??"Not found"),this.name="NotFoundError",this.status=404}},m=class extends d{constructor(n,r){super(n??"You are not authorised to perform this action."),this.name="UnauthorisedError",this.status=r??401}},c=class extends d{constructor(r,t){let o=t?` in ${t}`:"";super(`Schema validation failed${o}`);this.issues=r;this.source=t;this.name="SchemaValidationError",this.status=400}},y=class extends d{constructor(n,r){super(n),this.name="ApiError",this.status=r??500}},u=class extends d{constructor(r){super("Error parsing response into JSON.");this.response=r;this.name="ParsingError",this.status=500}};var j=["message","error","errors","exception","exceptions"];function D(e){console.log("json",e);let n=[];if(typeof e=="object"&&e!==null){for(let r of j)if(I(e,r)){console.log("hasProp",r,e[r]);let t=e[r];typeof t=="string"&&n.push(t),Array.isArray(t)&&t.every(o=>typeof o=="string")&&n.push(...t)}}return n.length===0&&n.push("Unknown error"),n.join(", ")}function w(e,n){if(n>=300&&n<=500){let r=D(e);throw n===404?new l(r):r===F?new m("You are not authenticated.",n):r===q?new m(r,n):new y(r,n)}}var O=e=>{let n={Accept:"application/json","Content-Type":"application/json","x-publishable-key":e.publishableKey};return{fetch:async(r,t={})=>{let o={...t,headers:{...t.headers,...n}},s=await fetch(`${e.baseUrl}${r}`,o);if(s.status===404)throw new l;let a=await s.json().catch(async()=>{throw new u(s)});return w(a,s.status),a}}},C={NotFound:l,Unauthorised:m,SchemaValidation:c,Api:y,JsonParsing:u};function K(e){return Object.values(C).some(n=>e instanceof n)}var N="1.17.2";var P={sandbox:"https://api.staging.inploi.com",production:"https://api.inploi.com",_internal_local:"http://api.test"},V=N;var f="isdk_session";var k=()=>typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"10000000-1000-4000-8000-100000000000".replace(/[018]/g,e=>(+e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>+e/4).toString(16));var R=e=>{let n=new Date;return n.setTime(n.getTime()+7*24*60*60*1e3),`${f}=${e};expires=${n.toUTCString()};path=/`},J=(e,n)=>{let r=e.get("session_id");if(n||r)return r;let t=sessionStorage.getItem(`${f}-session_id`);return typeof t=="string"?t:null},Y=new RegExp(`${f}=([^;]+)`),A=e=>{let n=e?e.url:location.href,{searchParams:r}=new URL(n),t=r.get("anonymous_id"),o=J(r,typeof window>"u");if(t)return{anonymous_id:t,session_id:o};let s=e?e.headers.get("cookie"):document.cookie;return s?{anonymous_id:Y.exec(s)?.[1]??null,session_id:o}:{anonymous_id:t,session_id:o}},G=()=>{if(typeof window>"u")throw new Error("getOrCreateAnonymousId() can only be called in browser environment");let e=A().anonymous_id;if(e)return e;let n=k();return document.cookie=R(n),n},W=e=>typeof e!="object"||e===null?null:{anonymous_id:"anonymous_id"in e&&typeof e.anonymous_id=="string"?e.anonymous_id:null,session_id:"session_id"in e&&typeof e.session_id=="string"?e.session_id:null},z=e=>e==="about:client"?"":e,X={pathname:"/log",method:"POST",schema:{response:_(),body:_()}},M=({rpcClient:e,logger:n,onEvent:r})=>({log:async o=>{E(o.request||typeof window<"u","Cannot log on the server without a request. Please pass a request to `log`.");let s="request"in o&&o.request?{href:o.request.url,referrer:z(o.request.referrer),title:""}:{href:location.href,referrer:document.referrer,title:document.title};try{let a={library:{name:"inploi-sdk",version:V},page:s},p=A(o.request),i={anonymous_id:p.anonymous_id,session_id:p.session_id,event:o.event,sent_at:new Date().toISOString(),context:a,properties:o.properties,custom_properties:o.customProperties},g=await e.request(X,{body:i}),v=W(g);return v?.anonymous_id&&(i.anonymous_id=v.anonymous_id),v?.session_id&&(i.session_id=v.session_id),typeof window<"u"&&i.anonymous_id&&(i.session_id&&sessionStorage.setItem(`${f}-session_id`,i.session_id.toString()),document.cookie=R(i.anonymous_id)),r?.(i),{success:!0,data:i}}catch(a){return n.error("Failed to send log to API. Inspect error response of `log` for more information."),{success:!1,error:a}}},getHeaders:o=>{let s=new Headers;return o?.anonymous_id&&s.append("Set-Cookie",R(o.anonymous_id)),s},getSessionInfo:A});import{stringify as Z}from"neoqs";function L(e,n,r){let t=e["~standard"].validate(n);if(t instanceof Promise)throw new TypeError("Async schema");if(t.issues)throw new c(t.issues,r);return t.value}function Q(e,n,r){try{return{success:!0,output:L(e,n,r)}}catch(t){if(t instanceof c)return{success:!1,issues:t.issues,source:t.source};throw t}}var h=class{constructor(n){if(this.baseUrl=P[n.environment],this.headers=new Headers({"Content-Type":"application/json",Accept:"application/json"}),n.apiKey.type==="secret"){if(typeof window<"u")throw new Error("Secret key cannot be used in a browser environment");this.headers.set("x-secret-key",n.apiKey.key)}else this.headers.set("x-publishable-key",n.apiKey.key);this.logger=n.logger,this._environment=n.environment}get environment(){return this._environment}getFetchParams(n,r){let t=r.validateIn??!0,{searchParams:o,body:s}=t?$(n,r):r,a=new URL(this.baseUrl),p=n.pathname;if("params"in r&&r.params)for(let[i,g]of Object.entries(r.params))p=p.replace(`:${i}`,String(g));return a.pathname=p,n.schema.searchParams&&(a.search=Z(o)),[a.toString(),{method:n.method,body:s?JSON.stringify(s):void 0,headers:this.headers,signal:r.signal}]}async parseResponse(n,r){let t=await r.response.json().catch(a=>{throw this.logger.error(a),new u(r.response)});if(!(r.validateOut??!0))return t;let s=Q(n.schema.response,t,"response");if(!s.success)throw w(t,r.response.status),new c(s.issues,s.source);return s.output}async request(n,r){try{let t=this.getFetchParams(n,r),o=await fetch(...t);return this.parseResponse(n,{response:o,validateOut:r.validateOut})}catch(t){throw t instanceof c?this.logger.error(t.message,t.issues):this.logger.error(t),t}}};function _(){return{"~standard":{vendor:"inploi",version:1,validate:e=>({value:e})}}}function U(e){return e}function $(e,n){let r={searchParams:void 0,body:void 0,validateIn:!1};return e.schema.searchParams&&(r.searchParams=L(e.schema.searchParams,"searchParams"in n?n.searchParams:{})),e.schema.body&&(r.body=L(e.schema.body,"body"in n?n.body:{})),r}function ee({publishableKey:e,env:n,logger:r=x,onEvent:t}){let o=O({baseUrl:P[n],publishableKey:e}),s=r===!1?b:r,a=new h({environment:n,apiKey:{type:"publishable",key:e},logger:s}),p=M({rpcClient:a,logger:s,onEvent:t});return{register:g=>g({logger:s,apiClient:o,analytics:p,rpcClient:a,publishableKey:e,env:n}),analytics:p,apiClient:o}}export{y as ApiError,h as InploiRpcClient,l as NotFoundError,u as ParsingError,c as SchemaValidationError,C as SdkError,m as UnauthorisedError,B as createPlugin,U as endpoint,k as generateUUID,G as getOrCreateAnonymousId,ee as initialiseSdk,x as inploiBrandedLogger,K as isSdkError,b as noLogging,_ as typed,$ as validateEndpointInputs};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sdk.logger.ts","../src/sdk.plugins.ts","../../core/src/common/common.utils.ts","../../core/src/common/common.currency.ts","../../core/src/common/common.datetime.ts","../src/sdk.api.ts","../package.json","../src/sdk.constants.ts","../src/sdk.analytics.ts","../src/sdk.rpc.ts","../src/sdk.ts"],"sourcesContent":["export const CONSOLE_PREFIX = '%c[inploi SDK]';\nexport const CONSOLE_STYLE = 'color: #65BC67; font-weight: bold;';\n\ntype LogMessage = (...data: any[]) => void;\nexport type Logger = {\n\twarn: LogMessage;\n\terror: LogMessage;\n\tinfo: LogMessage;\n\tlog: LogMessage;\n};\n\nexport const inploiBrandedLogger: Logger = {\n\twarn: (...args) => console.warn(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\terror: (...args) => console.error(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\tinfo: (...args) => console.info(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\tlog: (...args) => console.log(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n};\n\nexport const noLogging: Logger = { info: () => void 0, error: () => void 0, log: () => void 0, warn: () => void 0 };\n","import { AnalyticsService } from './sdk.analytics';\nimport { ApiClient } from './sdk.api';\nimport { Logger } from './sdk.logger';\nimport { InploiRpcClient } from './sdk.rpc';\n\nexport type PluginParams = {\n\tapiClient: ApiClient;\n\tlogger: Logger;\n};\n\nexport type Plugin<T extends string, P extends Record<string, unknown>> = {\n\tpluginName: T;\n\tpure_createActions: (params: PluginParams) => P;\n};\n\ntype PluginDependencies = {\n\tapiClient: ApiClient;\n\trpcClient: InploiRpcClient;\n\tlogger: Logger;\n\tanalytics: AnalyticsService;\n\t/** The publishable key used to initialise the SDK (available when registered via initialiseSdk) */\n\tpublishableKey?: string;\n};\n\nexport type InploiSdkPlugin = (dependencies: PluginDependencies) => any;\n\nexport const createPlugin = <T extends InploiSdkPlugin>(pluginFn: T) => pluginFn;\n","export const exhaustive = (value: never) => {\n\tthrow new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`);\n};\n\nexport function invariant(condition: any, message?: string): asserts condition {\n\tif (condition) {\n\t\treturn;\n\t}\n\n\tthrow new Error(message);\n}\n\nexport const uniqueOrThrow = <T>(array: T[]) => {\n\tconst uniqueValues = new Set(array);\n\n\tif (array.length !== uniqueValues.size) {\n\t\tthrow new Error('Duplicate values found');\n\t}\n\treturn true;\n};\n\nexport const uniqueByPropertyOrThrow =\n\t<T extends PropertyKey>(propertyKey: T) =>\n\t(array: { [K in T]: any }[]) => {\n\t\tconst values = array.map(item => item[propertyKey]);\n\t\tconst uniqueValues = new Set(values);\n\n\t\tif (values.length !== uniqueValues.size) {\n\t\t\tthrow new Error(`Duplicate values found for property: ${propertyKey.toString()}`);\n\t\t}\n\t\treturn true;\n\t};\n\n/**\n * A destructive way to ensure an object has a property.\n * This is useful when working with unknowns.\n */\nexport function hasProp<K extends PropertyKey>(data: object, prop: K): data is Record<K, unknown> {\n\treturn prop in data;\n}\n\n/**\n * A sort of type-safe way to check whether a key exists in an object.\n */\nexport function isKeyInObj<O extends Record<string, unknown>>(key: PropertyKey, obj: O): key is keyof O {\n\treturn key in obj;\n}\n","type TFunction = (key: 'competitive' | 'invalid_salary' | 'from' | 'up_to') => string;\n\ninterface SalaryParams {\n\tpay: string | null;\n\tpay_min: string | null;\n\tpay_mask: boolean;\n\tpay_max: string | null;\n\tpay_type: 'ANNUALLY' | 'HOURLY' | 'MONTHLY' | 'WEEKLY' | 'DAILY' | null;\n\tpay_currency: string;\n\tpay_display: boolean;\n}\n\nconst payPeriods: Record<NonNullable<SalaryParams['pay_type']>, string> = {\n\tANNUALLY: 'per year',\n\tDAILY: 'per day',\n\tHOURLY: 'per hour',\n\tMONTHLY: 'per month',\n\tWEEKLY: 'per week',\n};\n\nexport const getSalaryAsText = (params: {\n\tsalary: SalaryParams;\n\tconfig: { locales: string | string[] | undefined };\n\tt?: TFunction;\n}) => {\n\tconst { salary, config, t = s => s } = params;\n\tconst numberFormatter = new Intl.NumberFormat(config.locales, {\n\t\tstyle: 'currency',\n\t\tcurrency: salary.pay_currency,\n\t\ttrailingZeroDisplay: 'stripIfInteger',\n\t});\n\tif (salary.pay_display === false) return undefined;\n\tif (salary.pay === null && salary.pay_min === null && salary.pay_max === null) return undefined;\n\tif (salary.pay_mask) return t('competitive');\n\n\tif (salary.pay_max && Number.isNaN(+salary.pay_max)) return t('invalid_salary');\n\tif (salary.pay_min && Number.isNaN(+salary.pay_min)) return t('invalid_salary');\n\tif (salary.pay && Number.isNaN(+salary.pay)) return t('invalid_salary');\n\n\tconst period = salary.pay_type && salary.pay_type in payPeriods ? payPeriods[salary.pay_type] : undefined;\n\n\tif (salary.pay) return [numberFormatter.format(+salary.pay), period].filter(Boolean).join(' ');\n\n\tif (salary.pay_max && salary.pay_min)\n\t\treturn [numberFormatter.formatRange(+salary.pay_min, +salary.pay_max), period].filter(Boolean).join(' ') || '';\n\n\tif (salary.pay_max)\n\t\treturn `${t('up_to')} ${[numberFormatter.format(+salary.pay_max), period].filter(Boolean).join(' ')}`;\n\tif (salary.pay_min)\n\t\treturn `${t('from')} ${[numberFormatter.format(+salary.pay_min), period].filter(Boolean).join(' ')}`;\n\treturn t('invalid_salary');\n};\n","type TFunction = (key: 'today' | 'over_30_days_ago' | 'in_over_30_days') => string;\n\ntype Params = {\n\tfrom?: Date;\n\tto: string | number | Date;\n\tformatter?: Intl.RelativeTimeFormat;\n\tt?: TFunction;\n};\n\nconst DEFAULT_FORMATTER = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' });\n/** From a date, calculates the relative time difference from now */\nexport const getRelativeTimeDifference = ({\n\tfrom = new Date(),\n\tto,\n\tformatter = DEFAULT_FORMATTER,\n\tt = s => s,\n}: Params) => {\n\tconst then = to instanceof Date ? to : new Date(to);\n\tconst diff = then.getTime() - from.getTime();\n\n\tconst diffIn = {\n\t\tdays: Math.round(diff / 1000 / 60 / 60 / 24),\n\t\tmonths: Math.round(diff / 1000 / 60 / 60 / 24 / 30),\n\t};\n\n\tif (diffIn.days === 0) return t('today');\n\tif (Math.abs(diffIn.days) < 30) return formatter.format(diffIn.days, 'days');\n\tif (Math.abs(diffIn.days) < 3) return formatter.format(diffIn.months, 'months');\n\treturn diffIn.months < 0 ? t('over_30_days_ago') : t('in_over_30_days');\n};\n","import { hasProp } from '@inploi/core/common';\nimport { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport const unauthenticatedMessage = 'Unauthenticated';\nexport const unauthorisedMessage = 'This action is unauthorized.';\n\nexport class ErrorWithStatus extends Error {\n\tpublic status?: number;\n\tconstructor(message?: string, status?: number) {\n\t\tsuper(message);\n\t\tthis.status = status;\n\t\tthis.name = 'ErrorWithStatus';\n\t}\n}\n\nexport class NotFoundError extends ErrorWithStatus {\n\tconstructor(message?: string) {\n\t\tsuper(message ?? 'Not found');\n\t\tthis.name = 'NotFoundError';\n\t\tthis.status = 404;\n\t}\n}\n\nexport class UnauthorisedError extends ErrorWithStatus {\n\tconstructor(message?: string, status?: number) {\n\t\tsuper(message ?? 'You are not authorised to perform this action.');\n\t\tthis.name = 'UnauthorisedError';\n\t\tthis.status = status ?? 401;\n\t}\n}\n\nexport class SchemaValidationError extends ErrorWithStatus {\n\tconstructor(\n\t\tpublic issues: readonly StandardSchemaV1.Issue[],\n\t\tpublic source?: 'body' | 'searchParams' | 'response',\n\t) {\n\t\tconst sourceText = source ? ` in ${source}` : '';\n\t\tsuper(`Schema validation failed${sourceText}`);\n\t\tthis.name = 'SchemaValidationError';\n\t\tthis.status = 400;\n\t}\n}\n\nexport class ApiError extends ErrorWithStatus {\n\tconstructor(message: string, status?: number) {\n\t\tsuper(message);\n\t\tthis.name = 'ApiError';\n\t\tthis.status = status ?? 500;\n\t}\n}\n\nexport class JsonParsingError extends ErrorWithStatus {\n\tconstructor(public response?: Response) {\n\t\tsuper('Error parsing response into JSON.');\n\t\tthis.name = 'ParsingError';\n\t\tthis.status = 500;\n\t}\n}\n\n/** @deprecated - use `JsonParsingError` instead */\nexport class ParsingError extends JsonParsingError {}\n\nexport type ApiClient = {\n\tfetch: (pathname: string, options?: RequestInit) => Promise<unknown>;\n};\n\nconst ERROR_MESSAGE_KEYS = ['message', 'error', 'errors', 'exception', 'exceptions'] as const;\nfunction getErrorMessageFromJson(json: unknown): string {\n\tconsole.log('json', json);\n\tconst messages: string[] = [];\n\tif (typeof json === 'object' && json !== null) {\n\t\tfor (const key of ERROR_MESSAGE_KEYS) {\n\t\t\tif (hasProp(json, key)) {\n\t\t\t\tconsole.log('hasProp', key, json[key]);\n\t\t\t\tconst value = json[key];\n\t\t\t\tif (typeof value === 'string') messages.push(value);\n\t\t\t\tif (Array.isArray(value) && value.every((item): item is string => typeof item === 'string'))\n\t\t\t\t\tmessages.push(...value);\n\t\t\t}\n\t\t}\n\t}\n\tif (messages.length === 0) messages.push('Unknown error');\n\treturn messages.join(', ');\n}\n\n/** Throws branded errors when API returns a known error. */\nexport function handleApiExceptions(json: unknown, status: number) {\n\tif (status >= 300 && status <= 500) {\n\t\tconst message = getErrorMessageFromJson(json);\n\t\tif (status === 404) {\n\t\t\tthrow new NotFoundError(message);\n\t\t}\n\t\tif (message === unauthenticatedMessage) {\n\t\t\tthrow new UnauthorisedError('You are not authenticated.', status);\n\t\t}\n\t\tif (message === unauthorisedMessage) {\n\t\t\tthrow new UnauthorisedError(message, status);\n\t\t}\n\t\tthrow new ApiError(message, status);\n\t}\n}\n\nexport const createApiClient = (params: { baseUrl: string; publishableKey: string }): ApiClient => {\n\tconst defaultHeaders: HeadersInit = {\n\t\tAccept: 'application/json',\n\t\t'Content-Type': 'application/json',\n\t\t'x-publishable-key': params.publishableKey,\n\t};\n\n\treturn {\n\t\t/** Fetches from a pathname with a pre-established base path.\n\t\t * Parses received output as JSON, and throw if one of the common error messages is received.\n\t\t */\n\t\tfetch: async (pathname, options = {}) => {\n\t\t\tconst init = { ...options, headers: { ...options.headers, ...defaultHeaders } };\n\t\t\tconst response = await fetch(`${params.baseUrl}${pathname}`, init);\n\t\t\tif (response.status === 404) throw new NotFoundError();\n\n\t\t\tconst json = await response.json().catch(async () => {\n\t\t\t\tthrow new JsonParsingError(response);\n\t\t\t});\n\n\t\t\thandleApiExceptions(json, response.status);\n\n\t\t\t// We’re assuming no other exceptions have happened.\n\t\t\treturn json;\n\t\t},\n\t};\n};\n\nexport const SdkError = {\n\tNotFound: NotFoundError,\n\tUnauthorised: UnauthorisedError,\n\tSchemaValidation: SchemaValidationError,\n\tApi: ApiError,\n\tJsonParsing: JsonParsingError,\n};\n\nexport function isSdkError(error: unknown): error is (typeof SdkError)[keyof typeof SdkError] {\n\treturn Object.values(SdkError).some(ErrorClass => error instanceof ErrorClass);\n}\n","{\n\t\"name\": \"@inploi/sdk\",\n\t\"version\": \"1.17.0\",\n\t\"main\": \"dist/index.js\",\n\t\"types\": \"dist/index.d.ts\",\n\t\"license\": \"MIT\",\n\t\"files\": [\n\t\t\"/dist\",\n\t\t\"/cdn\"\n\t],\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"require\": \"./dist/index.js\",\n\t\t\t\"import\": \"./dist/index.mjs\",\n\t\t\t\"types\": \"./dist/index.d.ts\"\n\t\t}\n\t},\n\t\"scripts\": {\n\t\t\"build:npm\": \"tsup --dts --dts-resolve\",\n\t\t\"build:cdn\": \"tsup --config tsup.cdn.config.ts\",\n\t\t\"build\": \"concurrently 'pnpm run build:npm' 'pnpm run build:cdn'\",\n\t\t\"dev\": \"tsup --watch --config tsup.cdn.config.ts\",\n\t\t\"check\": \"eslint src --fix --max-warnings 0 && tsc\",\n\t\t\"test\": \"bun test\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@happy-dom/global-registrator\": \"^13.6.2\",\n\t\t\"@inploi/core\": \"workspace:*\",\n\t\t\"@total-typescript/ts-reset\": \"^0.5.1\",\n\t\t\"@types/bun\": \"^1.2.5\",\n\t\t\"@types/react\": \"^18.2.33\",\n\t\t\"@types/react-dom\": \"^18.2.14\",\n\t\t\"autoprefixer\": \"^10.4.16\",\n\t\t\"concurrently\": \"9.1.2\",\n\t\t\"eslint\": \"^7.32.0\",\n\t\t\"eslint-config-custom\": \"workspace:*\",\n\t\t\"happy-dom\": \"^12.6.0\",\n\t\t\"ts-toolbelt\": \"^9.6.0\",\n\t\t\"tsconfig\": \"workspace:*\",\n\t\t\"tsup\": \"^7.2.0\"\n\t},\n\t\"dependencies\": {\n\t\t\"@standard-schema/spec\": \"^1.0.0\",\n\t\t\"neoqs\": \"^6.13.0\"\n\t}\n}\n","import { version } from '../package.json';\n\n/**\n * The environment the SDK should run in.\n * - `production`: data will be stored and displayed on dashboards\n * - `sandbox`: data will be stored temporarily and purged periodically\n */\nexport type InploiSdkEnvironment = 'production' | 'sandbox';\n\nexport const ENV_TO_API_URL: Record<InploiSdkEnvironment, string> = {\n\tsandbox: 'https://api.staging.inploi.com',\n\tproduction: 'https://api.inploi.com',\n\t// @ts-expect-error - local test environment\n\t_internal_local: 'http://api.test',\n};\n\nexport const ANALYTICS_VERSION = version;\n\nexport const LOG_PATHNAME = '/log';\n\nexport const ANALYTICS_COOKIE_NAME = 'isdk_session';\n","import type { ResponseObj } from '@inploi/core/common';\nimport { invariant } from '@inploi/core/common';\n\nimport { InploiRpcClient, Logger, endpoint, typed } from '.';\nimport { ANALYTICS_COOKIE_NAME, ANALYTICS_VERSION } from './sdk.constants';\n\nconst formatCookie = (value: string) => {\n\tconst now = new Date();\n\tnow.setTime(now.getTime() + 7 * 24 * 60 * 60 * 1000); // 7 days expiration\n\n\treturn `${ANALYTICS_COOKIE_NAME}=${value};expires=${now.toUTCString()};path=/`;\n};\n\ntype FlowProperties = { flow_id: string; flow_version: number; flow_session_id: string; flow_build: number };\n\ntype JobProperties = {\n\tid: string;\n\tid_type: 'internal' | 'external';\n};\n\nexport type AnalyticsLogParams =\n\t| {\n\t\t\tevent: 'VIEW_JOB';\n\t\t\tproperties: { job: JobProperties };\n\t }\n\t| {\n\t\t\tevent: 'FLOW_REDIRECT';\n\t\t\tproperties: { href: string; job: JobProperties | undefined } & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'FLOW_START' | 'FLOW_END';\n\t\t\tproperties: { job: JobProperties | undefined } & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'FLOW_SUBMIT';\n\t\t\tproperties: {\n\t\t\t\tservice: string;\n\t\t\t\tresponse: {\n\t\t\t\t\tstatus: number;\n\t\t\t\t\tpayload: unknown;\n\t\t\t\t};\n\t\t\t\tjob: JobProperties | undefined;\n\t\t\t} & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'SUBMIT_FORM' | 'VIEW_PAGE';\n\t\t\tproperties?: {\n\t\t\t\tjob: JobProperties | undefined;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'IDENTIFY';\n\t\t\tproperties: {\n\t\t\t\tidentifier: string;\n\t\t\t\tfirst_name?: string;\n\t\t\t\tlast_name?: string;\n\t\t\t\tphone_number?: string;\n\t\t\t\temail?: string;\n\t\t\t\tcustom_traits?: Record<string, unknown>;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_PAGINATE';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_SETTLE';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_JOB_CLICK';\n\t\t\tproperties: {\n\t\t\t\tjob_id: number;\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'VIEW_SEARCH';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'FEEDBACK';\n\t\t\tproperties: {\n\t\t\t\tkey: string;\n\t\t\t\tscore?: -1 | 0 | 1;\n\t\t\t\tcomment?: string;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'LINK_CLICK';\n\t\t\tproperties: {\n\t\t\t\ttarget_href: string;\n\t\t\t\tjob_id: string | undefined;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'INTERACTION';\n\t\t\tproperties: {\n\t\t\t\ttag: string;\n\t\t\t};\n\t };\n\nexport type AnalyticsLogEvent = AnalyticsLogParams['event'];\n\ntype EventPropertyMap = {\n\t[Param in AnalyticsLogParams as Param['event']]: Omit<Param, 'event'>;\n};\n\ntype AnalyticsContext = {\n\tlibrary: {\n\t\tname: 'inploi-sdk';\n\t\tversion: string;\n\t};\n\tpage: {\n\t\thref: string;\n\t\treferrer: string;\n\t\ttitle: string;\n\t};\n};\n\ntype TrackPayload<P = EventPropertyMap[keyof EventPropertyMap]['properties']> = {\n\tanonymous_id: string | null;\n\tsession_id: string | null;\n\tevent: AnalyticsLogEvent;\n\tsent_at: string;\n\tcontext: AnalyticsContext;\n\tproperties: P;\n\tcustom_properties?: Record<string, unknown>;\n};\n\ntype LogFnParams<T extends keyof EventPropertyMap> = {\n\tevent: T;\n\tcustomProperties?: Record<string, unknown>;\n\t/** Passing a request will make logging possible on a server environment. */\n\trequest?: Request;\n} & EventPropertyMap[T];\n\ntype LogFn = <TEvent extends keyof EventPropertyMap>(\n\tparams: LogFnParams<TEvent>,\n) => Promise<ResponseObj<TrackPayload<EventPropertyMap[TEvent]['properties']>>>;\n\nexport type AnalyticsService = {\n\tlog: LogFn;\n\t/** From a log payload data, generate headers to use in server environments to update the anonymous_id */\n\tgetHeaders: (payload?: TrackPayload) => Headers;\n\tgetSessionInfo: typeof getSessionInfo;\n};\n\nconst getSessionId = (searchParams: URLSearchParams, isServer: boolean) => {\n\tconst fromSearchParams = searchParams.get('session_id');\n\tif (isServer) return fromSearchParams;\n\tif (fromSearchParams) return fromSearchParams;\n\tconst fromSessionStorage = sessionStorage.getItem(`${ANALYTICS_COOKIE_NAME}-session_id`);\n\tif (typeof fromSessionStorage === 'string') return fromSessionStorage;\n\treturn null;\n};\n\nconst cookieRegex = new RegExp(`${ANALYTICS_COOKIE_NAME}=([^;]+)`);\nconst getSessionInfo = (request?: Request) => {\n\tconst href = request ? request.url : location.href;\n\tconst { searchParams } = new URL(href);\n\tconst anonymous_id = searchParams.get('anonymous_id');\n\tconst session_id = getSessionId(searchParams, typeof window === 'undefined');\n\n\t// If there's an anonymous_id in the search params, use it\n\tif (anonymous_id)\n\t\treturn {\n\t\t\tanonymous_id,\n\t\t\tsession_id,\n\t\t};\n\n\t// If there's a cookie, use it\n\tconst cookie = request ? request.headers.get('cookie') : document.cookie;\n\tif (cookie) {\n\t\tconst match = cookieRegex.exec(cookie);\n\t\tconst anonymous_id = match?.[1];\n\t\treturn {\n\t\t\tanonymous_id: anonymous_id ?? null,\n\t\t\tsession_id,\n\t\t};\n\t}\n\n\t// Otherwise, return what we have\n\treturn {\n\t\tanonymous_id,\n\t\tsession_id,\n\t};\n};\n\n/**\n * Get or create a persistent anonymous ID.\n *\n * This is the universal identifier that bridges:\n * - SDK analytics (Laravel tracking)\n * - Agent conversations (Durable Object routing)\n * - Identity resolution\n *\n * The ID is:\n * - Generated client-side if none exists\n * - Persisted in cookie for 7 days\n * - The same across all SDK plugins\n *\n * @returns The anonymous ID (existing or newly generated)\n */\nexport const getOrCreateAnonymousId = (): string => {\n\t// Server-side: cannot generate, return empty (should not happen in normal flow)\n\tif (typeof window === 'undefined') {\n\t\tthrow new Error('getOrCreateAnonymousId() can only be called in browser environment');\n\t}\n\n\t// Check existing sources first\n\tconst existing = getSessionInfo().anonymous_id;\n\tif (existing) return existing;\n\n\t// Generate new ID and immediately persist to cookie\n\tconst newId = crypto.randomUUID();\n\tdocument.cookie = formatCookie(newId);\n\treturn newId;\n};\n\nconst getSessionInfoFromResponse = (response: unknown) => {\n\tif (typeof response !== 'object' || response === null) return null;\n\treturn {\n\t\tanonymous_id:\n\t\t\t'anonymous_id' in response && typeof response.anonymous_id === 'string' ? response.anonymous_id : null,\n\t\tsession_id: 'session_id' in response && typeof response.session_id === 'string' ? response.session_id : null,\n\t};\n};\n\nconst serverReferrer = (referrer: typeof Request.prototype.referrer) => {\n\tif (referrer === 'about:client') return '';\n\treturn referrer;\n};\n\nconst analyticsLogEndpoint = endpoint({\n\tpathname: '/log',\n\tmethod: 'POST',\n\tschema: {\n\t\tresponse: typed<unknown>(),\n\t\tbody: typed<TrackPayload>(),\n\t},\n});\n\nexport type AnalyticsOnEventCallback = (event: AnalyticsLogParams) => void;\n\nexport const createAnalyticsService = ({\n\trpcClient,\n\tlogger,\n\tonEvent,\n}: {\n\tlogger: Logger;\n\trpcClient: InploiRpcClient;\n\tonEvent?: AnalyticsOnEventCallback;\n}): AnalyticsService => {\n\tconst logFn: LogFn = async params => {\n\t\tinvariant(\n\t\t\tparams.request || typeof window !== 'undefined',\n\t\t\t'Cannot log on the server without a request. Please pass a request to `log`.',\n\t\t);\n\n\t\t// if there’s a request, use it instead of browser APIs\n\t\tconst page =\n\t\t\t'request' in params && params.request ?\n\t\t\t\t{\n\t\t\t\t\thref: params.request.url,\n\t\t\t\t\treferrer: serverReferrer(params.request.referrer),\n\t\t\t\t\ttitle: '',\n\t\t\t\t}\n\t\t\t:\t{\n\t\t\t\t\thref: location.href,\n\t\t\t\t\treferrer: document.referrer,\n\t\t\t\t\ttitle: document.title,\n\t\t\t\t};\n\n\t\ttry {\n\t\t\tconst context: AnalyticsContext = {\n\t\t\t\tlibrary: {\n\t\t\t\t\tname: 'inploi-sdk',\n\t\t\t\t\tversion: ANALYTICS_VERSION,\n\t\t\t\t},\n\t\t\t\tpage,\n\t\t\t};\n\n\t\t\tconst sessionInfo = getSessionInfo(params.request);\n\t\t\tconst payload: TrackPayload = {\n\t\t\t\tanonymous_id: sessionInfo.anonymous_id,\n\t\t\t\tsession_id: sessionInfo.session_id,\n\t\t\t\tevent: params.event,\n\t\t\t\tsent_at: new Date().toISOString(),\n\t\t\t\tcontext,\n\t\t\t\tproperties: params.properties,\n\t\t\t\tcustom_properties: params.customProperties,\n\t\t\t};\n\n\t\t\tconst responseJson = await rpcClient.request(analyticsLogEndpoint, {\n\t\t\t\tbody: payload,\n\t\t\t});\n\n\t\t\tconst newSession = getSessionInfoFromResponse(responseJson);\n\t\t\tif (newSession?.anonymous_id) {\n\t\t\t\tpayload.anonymous_id = newSession.anonymous_id;\n\t\t\t}\n\t\t\tif (newSession?.session_id) {\n\t\t\t\tpayload.session_id = newSession.session_id;\n\t\t\t}\n\n\t\t\tif (typeof window !== 'undefined' && payload.anonymous_id) {\n\t\t\t\tif (payload.session_id) {\n\t\t\t\t\tsessionStorage.setItem(`${ANALYTICS_COOKIE_NAME}-session_id`, payload.session_id.toString());\n\t\t\t\t}\n\t\t\t\tdocument.cookie = formatCookie(payload.anonymous_id);\n\t\t\t}\n\n\t\t\tonEvent?.(payload as AnalyticsLogParams);\n\t\t\treturn { success: true, data: payload };\n\t\t} catch (e) {\n\t\t\t/** We dont’t log any PII on the console */\n\t\t\tlogger.error('Failed to send log to API. Inspect error response of `log` for more information.');\n\t\t\treturn { success: false, error: e };\n\t\t}\n\t};\n\n\treturn {\n\t\tlog: logFn,\n\t\tgetHeaders: payload => {\n\t\t\tconst headers = new Headers();\n\t\t\tif (!payload?.anonymous_id) return headers;\n\n\t\t\theaders.append('Set-Cookie', formatCookie(payload.anonymous_id));\n\t\t\treturn headers;\n\t\t},\n\t\tgetSessionInfo,\n\t};\n};\n","import type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { stringify } from 'neoqs';\n\nimport { JsonParsingError, SchemaValidationError, handleApiExceptions } from './sdk.api';\nimport { ENV_TO_API_URL, InploiSdkEnvironment } from './sdk.constants';\nimport { Logger } from './sdk.logger';\n\ntype RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\n\n/** Extract parameter names from a pathname string */\ntype ExtractParamNames<T extends string> =\n\tT extends `${infer _Before}:${infer Param}/${infer After}` ? Param | ExtractParamNames<`/${After}`>\n\t: T extends `${infer _Before}:${infer Param}` ? Param\n\t: never;\n\n/** Create params object from parameter names */\ntype ExtractPathParams<T extends string> =\n\tstring extends T ? Record<string, string | number>\n\t: ExtractParamNames<T> extends never ? Record<string, never>\n\t: { [K in ExtractParamNames<T>]: string | number };\n\n/** Parses a StandardSchemaV1 schema and input into an output. */\nexport function parse<T extends StandardSchemaV1>(\n\tschema: T,\n\tinput: StandardSchemaV1.InferInput<T>,\n\tsource?: 'body' | 'searchParams' | 'response',\n): StandardSchemaV1.InferOutput<T> {\n\tconst result = schema['~standard'].validate(input);\n\tif (result instanceof Promise) {\n\t\tthrow new TypeError('Async schema');\n\t}\n\n\tif (result.issues) {\n\t\tthrow new SchemaValidationError(result.issues, source);\n\t}\n\n\treturn result.value;\n}\n\n/** Parses a StandardSchemaV1 schema and input into an output, returning a success flag and issues if the parse fails. */\nexport function safeParse<T extends StandardSchemaV1>(\n\tschema: T,\n\tinput: StandardSchemaV1.InferInput<T>,\n\tsource?: 'body' | 'searchParams' | 'response',\n):\n\t| {\n\t\t\tsuccess: true;\n\t\t\toutput: StandardSchemaV1.InferOutput<T>;\n\t }\n\t| {\n\t\t\tsuccess: false;\n\t\t\tissues: readonly StandardSchemaV1.Issue[];\n\t\t\tsource?: 'body' | 'searchParams' | 'response';\n\t } {\n\ttry {\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\toutput: parse(schema, input, source),\n\t\t};\n\t} catch (e) {\n\t\tif (e instanceof SchemaValidationError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tissues: e.issues,\n\t\t\t\tsource: e.source,\n\t\t\t};\n\t\t}\n\t\tthrow e;\n\t}\n}\n\nexport interface InploiRpcClientParams {\n\tenvironment: InploiSdkEnvironment;\n\tlogger: Logger;\n\tapiKey:\n\t\t| {\n\t\t\t\t/** Makes the API call with an x-secret-key header\n\t\t\t\t * This will error if used in a browser environment.\n\t\t\t\t */\n\t\t\t\ttype: 'secret';\n\t\t\t\tkey: string;\n\t\t }\n\t\t| {\n\t\t\t\t/** Makes the API call with an x-publishable-key header\n\t\t\t\t * This can be called in a browser or server environment.\n\t\t\t\t */\n\t\t\t\ttype: 'publishable';\n\t\t\t\tkey: string;\n\t\t };\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\ntype NonReducibleUnknown = {} | null | undefined;\ntype LooseAutocomplete<T extends BaseType, BaseType> = T | BaseType;\n\n/** RPC client for making API calls to the Inploi API. */\nexport class InploiRpcClient {\n\tprivate baseUrl: string;\n\tprivate headers: Headers;\n\tprivate logger: Logger;\n\tprivate _environment: InploiSdkEnvironment;\n\n\tconstructor(params: InploiRpcClientParams) {\n\t\tthis.baseUrl = ENV_TO_API_URL[params.environment];\n\t\tthis.headers = new Headers({\n\t\t\t'Content-Type': 'application/json',\n\t\t\tAccept: 'application/json',\n\t\t});\n\t\tif (params.apiKey.type === 'secret') {\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\tthrow new Error('Secret key cannot be used in a browser environment');\n\t\t\t}\n\t\t\tthis.headers.set('x-secret-key', params.apiKey.key);\n\t\t} else {\n\t\t\tthis.headers.set('x-publishable-key', params.apiKey.key);\n\t\t}\n\t\tthis.logger = params.logger;\n\t\tthis._environment = params.environment;\n\t}\n\n\tget environment() {\n\t\treturn this._environment;\n\t}\n\n\t/** Gets params for a fetch request to the given endpoint */\n\tgetFetchParams<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: T extends RpcEndpoint<infer _, infer _TPathname, infer TPathParams, infer TSearch, infer TBody> ?\n\t\t\tGetSchemaValues<{\n\t\t\t\tbody: TBody;\n\t\t\t\tsearchParams: TSearch;\n\t\t\t\tparams: TPathParams;\n\t\t\t}> & {\n\t\t\t\tsignal?: AbortSignal;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the inputs against the schema.\n\t\t\t\t * If you want to skip validation (e.g.: already validated yourself or with `validateEndpontInputs`), set this to false.\n\t\t\t\t */\n\t\t\t\tvalidateIn?: boolean;\n\t\t\t}\n\t\t:\tnever,\n\t): [url: string, options: RequestInit] {\n\t\tconst validateIn = options.validateIn ?? true;\n\t\tconst { searchParams, body } = validateIn ? validateEndpointInputs(endpoint, options) : options;\n\n\t\tconst url = new URL(this.baseUrl);\n\n\t\t// Replace path parameters in pathname\n\t\tlet pathname = endpoint.pathname;\n\t\tif ('params' in options && options.params) {\n\t\t\tfor (const [key, value] of Object.entries(options.params)) {\n\t\t\t\tpathname = pathname.replace(`:${key}`, String(value));\n\t\t\t}\n\t\t}\n\t\turl.pathname = pathname;\n\n\t\tif (endpoint.schema.searchParams) {\n\t\t\turl.search = stringify(searchParams);\n\t\t}\n\n\t\treturn [\n\t\t\turl.toString(),\n\t\t\t{\n\t\t\t\tmethod: endpoint.method,\n\t\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t\t\theaders: this.headers,\n\t\t\t\tsignal: options.signal,\n\t\t\t},\n\t\t];\n\t}\n\n\t/** Parses a response against an endpoint’s response schema, considering common errors thrown from the API.\n\t * @throws {JsonParsingError} - If the response is not valid JSON.\n\t * @throws {SchemaValidationError} - If the response does not match the schema.\n\t * @throws {ApiError} - If the API responded with an error message.\n\t */\n\tasync parseResponse<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: {\n\t\t\tresponse: Response;\n\t\t\t/**\n\t\t\t * Whether to validate the response against the schema.\n\t\t\t * This is meant more as an escape hatch for when the response is not as expected and you want to handle it separately yourself.\n\t\t\t * ⚠️ This will lead to potential type/runtime mismatch as it does not verify the response against the schema.\n\t\t\t */\n\t\t\tvalidateOut?: boolean;\n\t\t},\n\t): Promise<StandardSchemaV1.InferOutput<T['schema']['response']>> {\n\t\tconst json = await options.response.json().catch(e => {\n\t\t\tthis.logger.error(e);\n\t\t\tthrow new JsonParsingError(options.response);\n\t\t});\n\n\t\tconst validateOut = options.validateOut ?? true;\n\t\tif (!validateOut) return json as StandardSchemaV1.InferOutput<T['schema']['response']>;\n\n\t\tconst result = safeParse(endpoint.schema.response, json, 'response');\n\t\tif (!result.success) {\n\t\t\thandleApiExceptions(json, options.response.status);\n\t\t\tthrow new SchemaValidationError(result.issues, result.source);\n\t\t}\n\n\t\treturn result.output as StandardSchemaV1.InferOutput<T['schema']['response']>;\n\t}\n\n\t/** Fetches, parses and validates an API endpoint.\n\t * Logs errors and throws them again so that the caller can handle them.\n\t *\n\t * @throws {JsonParsingError} - If the response is not valid JSON.\n\t * @throws {SchemaValidationError} - If the searchParams, body or response does not match the schema.\n\t * @throws {ApiError} - If the API responded with an error message.\n\t * @throws {UnauthorisedError} - If the request is unauthorised either by missing key or unmet permissions.\n\t * @throws {NotFoundError} - If the endpoint is not found.\n\t * @throws {Error} - Another unhandled error.\n\t */\n\tasync request<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: T extends RpcEndpoint<infer _, infer _TPathname, infer TPathParams, infer TSearch, infer TBody> ?\n\t\t\tGetSchemaValues<{\n\t\t\t\tbody: TBody;\n\t\t\t\tsearchParams: TSearch;\n\t\t\t\tparams: TPathParams;\n\t\t\t}> & {\n\t\t\t\tsignal?: AbortSignal;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the inputs against the schema.\n\t\t\t\t * If you want to skip validation (e.g.: already validated yourself or with `validateEndpontInputs`), set this to false.\n\t\t\t\t */\n\t\t\t\tvalidateIn?: boolean;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the response against the schema.\n\t\t\t\t * This is meant more as an escape hatch for when the response is not as expected and you want to handle it separately yourself.\n\t\t\t\t * ⚠️ This will lead to potential type/runtime mismatch as it does not verify the response against the schema.\n\t\t\t\t */\n\t\t\t\tvalidateOut?: boolean;\n\t\t\t}\n\t\t:\tnever,\n\t): Promise<StandardSchemaV1.InferOutput<T['schema']['response']>> {\n\t\ttry {\n\t\t\tconst fetchParams = this.getFetchParams(endpoint, options);\n\t\t\tconst response = await fetch(...fetchParams);\n\t\t\treturn this.parseResponse(endpoint, { response, validateOut: options.validateOut });\n\t\t} catch (e) {\n\t\t\tif (e instanceof SchemaValidationError) {\n\t\t\t\tthis.logger.error(e.message, e.issues);\n\t\t\t} else {\n\t\t\t\tthis.logger.error(e);\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t}\n}\n\ntype GetSchemaValues<T extends { searchParams: any; body: any; params?: any }> = {\n\t[K in keyof T as T[K] extends never ? never\n\t: T[K] extends Record<string, never> ? never\n\t: K]: T[K] extends never ? never : LooseAutocomplete<T[K], NonReducibleUnknown>;\n};\n\n/**\n * Typed but *not runtime validated* schema\n * useful for type-checking the schema without bundling validation schemas\n */\nexport function typed<T>(): StandardSchemaV1<T, T> {\n\treturn {\n\t\t'~standard': {\n\t\t\tvendor: 'inploi',\n\t\t\tversion: 1,\n\t\t\tvalidate: input => {\n\t\t\t\treturn {\n\t\t\t\t\tvalue: input as T,\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t};\n}\n\nexport interface RpcEndpoint<\n\tTMethod extends RequestMethod = RequestMethod,\n\tTPathname extends string = string,\n\tTPathParams = any,\n\tTSearch = any,\n\tTBody = any,\n\tTResponse = any,\n> {\n\tpathname: TPathname;\n\tmethod: TMethod;\n\theaders?: Headers;\n\tschema: {\n\t\tsearchParams?: StandardSchemaV1<TSearch, TSearch>;\n\t\tbody?: StandardSchemaV1<TBody, TBody>;\n\t\tresponse: StandardSchemaV1<TResponse, TResponse>;\n\t};\n\t/** Type-only property to store path parameter types */\n\treadonly __pathParams?: TPathParams;\n}\n\nexport function endpoint<\n\tTMethod extends RequestMethod,\n\tTPathname extends string,\n\tTSearch extends StandardSchemaV1 | never = never,\n\tTBody extends StandardSchemaV1 | never = never,\n\tTResponse extends StandardSchemaV1 | never = never,\n>(endpoint: {\n\tpathname: TPathname;\n\tmethod: TMethod;\n\theaders?: Headers;\n\tschema: {\n\t\tsearchParams?: TSearch;\n\t\tbody?: TBody;\n\t\tresponse: TResponse;\n\t};\n}) {\n\ttype PathParams = ExtractPathParams<TPathname>;\n\treturn endpoint as RpcEndpoint<\n\t\tTMethod,\n\t\tTPathname,\n\t\tPathParams,\n\t\tStandardSchemaV1.InferInput<TSearch>,\n\t\tStandardSchemaV1.InferInput<TBody>,\n\t\tStandardSchemaV1.InferOutput<TResponse>\n\t>;\n}\n\n/** Validates the inputs for an endpoint ahead of time\n * Useful when you need to validate and throw earlier, or use the inputs for something other than the API call.\n */\nexport function validateEndpointInputs<T extends RpcEndpoint>(\n\tendpoint: T,\n\toptions: GetSchemaValues<{ body: unknown; searchParams: unknown }>,\n) {\n\tconst validatedInputs = {\n\t\tsearchParams: undefined,\n\t\tbody: undefined,\n\t\tvalidateIn: false,\n\t} as T extends RpcEndpoint<infer _, infer __, infer ___, infer TSearch, infer TBody> ?\n\t\tGetSchemaValues<{\n\t\t\tbody: TBody;\n\t\t\tsearchParams: TSearch;\n\t\t}> & {\n\t\t\tvalidateIn: false;\n\t\t}\n\t:\tnever;\n\n\tif (endpoint.schema.searchParams) {\n\t\tvalidatedInputs.searchParams = parse(\n\t\t\tendpoint.schema.searchParams,\n\t\t\t'searchParams' in options ? options.searchParams : {},\n\t\t);\n\t}\n\n\tif (endpoint.schema.body) {\n\t\tvalidatedInputs.body = parse(endpoint.schema.body, 'body' in options ? options.body : {});\n\t}\n\n\treturn validatedInputs;\n}\n","import { AnalyticsOnEventCallback, createAnalyticsService } from './sdk.analytics';\nimport { createApiClient } from './sdk.api';\nimport { ENV_TO_API_URL, InploiSdkEnvironment } from './sdk.constants';\nimport { Logger, inploiBrandedLogger, noLogging } from './sdk.logger';\nimport { InploiSdkPlugin } from './sdk.plugins';\nimport { InploiRpcClient } from './sdk.rpc';\n\nexport type InitialiseInploiSdkParams = {\n\t/** Your public API key for the inploi SDK. */\n\tpublishableKey: string;\n\t/** Which app environment to run. This ultimately affects which inploi endpoints to gather data are going to be used.\n\t * Anything other than `production` should be considered a development environment and the data periodicaly purged. */\n\tenv: InploiSdkEnvironment;\n\t/** Logger object that handles logging of different levels.\n\t * You can override this to use your own logger, or to disable logging altogether by passing`false`.\n\t * @default inploiBrandedLogger\n\t * */\n\tlogger?: Logger | false;\n\n\t/** When provided, this callback will be called with every event that is logged to the analytics service. */\n\tonEvent?: AnalyticsOnEventCallback;\n};\n\nexport function initialiseSdk({\n\tpublishableKey,\n\tenv,\n\tlogger = inploiBrandedLogger,\n\tonEvent,\n}: InitialiseInploiSdkParams) {\n\t/** @deprecated - use `rpcClient` instead */\n\tconst apiClient = createApiClient({ baseUrl: ENV_TO_API_URL[env], publishableKey });\n\tconst loggerService = logger === false ? noLogging : logger;\n\tconst rpcClient = new InploiRpcClient({\n\t\tenvironment: env,\n\t\tapiKey: { type: 'publishable', key: publishableKey },\n\t\tlogger: loggerService,\n\t});\n\tconst analytics = createAnalyticsService({ rpcClient, logger: loggerService, onEvent });\n\n\tconst register = <P extends InploiSdkPlugin>(plugin: P): ReturnType<P> => {\n\t\treturn plugin({ logger: loggerService, apiClient, analytics, rpcClient, publishableKey });\n\t};\n\n\treturn { register, analytics, apiClient };\n}\n\nexport type InploiSdk = ReturnType<typeof initialiseSdk>;\n"],"mappings":"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","names":["CONSOLE_PREFIX","CONSOLE_STYLE","inploiBrandedLogger","args","noLogging","createPlugin","pluginFn","invariant","condition","message","hasProp","data","prop","DEFAULT_FORMATTER","unauthenticatedMessage","unauthorisedMessage","ErrorWithStatus","message","status","NotFoundError","UnauthorisedError","SchemaValidationError","issues","source","sourceText","ApiError","JsonParsingError","response","ERROR_MESSAGE_KEYS","getErrorMessageFromJson","json","messages","key","hasProp","value","item","handleApiExceptions","status","message","NotFoundError","unauthenticatedMessage","UnauthorisedError","unauthorisedMessage","ApiError","createApiClient","params","defaultHeaders","pathname","options","init","response","JsonParsingError","SdkError","SchemaValidationError","isSdkError","error","ErrorClass","version","ENV_TO_API_URL","ANALYTICS_VERSION","version","ANALYTICS_COOKIE_NAME","formatCookie","value","now","ANALYTICS_COOKIE_NAME","getSessionId","searchParams","isServer","fromSearchParams","fromSessionStorage","cookieRegex","getSessionInfo","request","href","anonymous_id","session_id","cookie","getOrCreateAnonymousId","existing","newId","getSessionInfoFromResponse","response","serverReferrer","referrer","analyticsLogEndpoint","typed","createAnalyticsService","rpcClient","logger","onEvent","params","invariant","page","context","ANALYTICS_VERSION","sessionInfo","payload","responseJson","newSession","e","headers","stringify","parse","schema","input","source","result","SchemaValidationError","safeParse","e","InploiRpcClient","params","ENV_TO_API_URL","endpoint","options","validateIn","searchParams","body","validateEndpointInputs","url","pathname","key","value","stringify","json","JsonParsingError","handleApiExceptions","fetchParams","response","typed","validatedInputs","initialiseSdk","publishableKey","env","logger","inploiBrandedLogger","onEvent","apiClient","createApiClient","ENV_TO_API_URL","loggerService","noLogging","rpcClient","InploiRpcClient","analytics","createAnalyticsService","plugin"]}
1
+ {"version":3,"sources":["../src/sdk.logger.ts","../src/sdk.plugins.ts","../../core/src/common/common.utils.ts","../../core/src/common/common.currency.ts","../../core/src/common/common.datetime.ts","../src/sdk.api.ts","../package.json","../src/sdk.constants.ts","../src/sdk.uuid.ts","../src/sdk.analytics.ts","../src/sdk.rpc.ts","../src/sdk.ts"],"sourcesContent":["export const CONSOLE_PREFIX = '%c[inploi SDK]';\nexport const CONSOLE_STYLE = 'color: #65BC67; font-weight: bold;';\n\ntype LogMessage = (...data: any[]) => void;\nexport type Logger = {\n\twarn: LogMessage;\n\terror: LogMessage;\n\tinfo: LogMessage;\n\tlog: LogMessage;\n};\n\nexport const inploiBrandedLogger: Logger = {\n\twarn: (...args) => console.warn(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\terror: (...args) => console.error(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\tinfo: (...args) => console.info(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n\tlog: (...args) => console.log(CONSOLE_PREFIX, CONSOLE_STYLE, ...args),\n};\n\nexport const noLogging: Logger = { info: () => void 0, error: () => void 0, log: () => void 0, warn: () => void 0 };\n","import { AnalyticsService } from './sdk.analytics';\nimport { ApiClient } from './sdk.api';\nimport { InploiSdkEnvironment } from './sdk.constants';\nimport { Logger } from './sdk.logger';\nimport { InploiRpcClient } from './sdk.rpc';\n\nexport type PluginParams = {\n\tapiClient: ApiClient;\n\tlogger: Logger;\n};\n\nexport type Plugin<T extends string, P extends Record<string, unknown>> = {\n\tpluginName: T;\n\tpure_createActions: (params: PluginParams) => P;\n};\n\ntype PluginDependencies = {\n\tapiClient: ApiClient;\n\trpcClient: InploiRpcClient;\n\tlogger: Logger;\n\tanalytics: AnalyticsService;\n\t/** The publishable key used to initialise the SDK (available when registered via initialiseSdk) */\n\tpublishableKey?: string;\n\t/** The environment the SDK was initialised with — plugins can use this to select the correct service URL */\n\tenv?: InploiSdkEnvironment;\n};\n\nexport type InploiSdkPlugin = (dependencies: PluginDependencies) => any;\n\nexport const createPlugin = <T extends InploiSdkPlugin>(pluginFn: T) => pluginFn;\n","export const exhaustive = (value: never) => {\n\tthrow new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`);\n};\n\nexport function invariant(condition: any, message?: string): asserts condition {\n\tif (condition) {\n\t\treturn;\n\t}\n\n\tthrow new Error(message);\n}\n\nexport const uniqueOrThrow = <T>(array: T[]) => {\n\tconst uniqueValues = new Set(array);\n\n\tif (array.length !== uniqueValues.size) {\n\t\tthrow new Error('Duplicate values found');\n\t}\n\treturn true;\n};\n\nexport const uniqueByPropertyOrThrow =\n\t<T extends PropertyKey>(propertyKey: T) =>\n\t(array: { [K in T]: any }[]) => {\n\t\tconst values = array.map(item => item[propertyKey]);\n\t\tconst uniqueValues = new Set(values);\n\n\t\tif (values.length !== uniqueValues.size) {\n\t\t\tthrow new Error(`Duplicate values found for property: ${propertyKey.toString()}`);\n\t\t}\n\t\treturn true;\n\t};\n\n/**\n * A destructive way to ensure an object has a property.\n * This is useful when working with unknowns.\n */\nexport function hasProp<K extends PropertyKey>(data: object, prop: K): data is Record<K, unknown> {\n\treturn prop in data;\n}\n\n/**\n * A sort of type-safe way to check whether a key exists in an object.\n */\nexport function isKeyInObj<O extends Record<string, unknown>>(key: PropertyKey, obj: O): key is keyof O {\n\treturn key in obj;\n}\n","type TFunction = (key: 'competitive' | 'invalid_salary' | 'from' | 'up_to') => string;\n\ninterface SalaryParams {\n\tpay: string | null;\n\tpay_min: string | null;\n\tpay_mask: boolean;\n\tpay_max: string | null;\n\tpay_type: 'ANNUALLY' | 'HOURLY' | 'MONTHLY' | 'WEEKLY' | 'DAILY' | null;\n\tpay_currency: string;\n\tpay_display: boolean;\n}\n\nconst payPeriods: Record<NonNullable<SalaryParams['pay_type']>, string> = {\n\tANNUALLY: 'per year',\n\tDAILY: 'per day',\n\tHOURLY: 'per hour',\n\tMONTHLY: 'per month',\n\tWEEKLY: 'per week',\n};\n\nexport const getSalaryAsText = (params: {\n\tsalary: SalaryParams;\n\tconfig: { locales: string | string[] | undefined };\n\tt?: TFunction;\n}) => {\n\tconst { salary, config, t = s => s } = params;\n\tconst numberFormatter = new Intl.NumberFormat(config.locales, {\n\t\tstyle: 'currency',\n\t\tcurrency: salary.pay_currency,\n\t\ttrailingZeroDisplay: 'stripIfInteger',\n\t});\n\tif (salary.pay_display === false) return undefined;\n\tif (salary.pay === null && salary.pay_min === null && salary.pay_max === null) return undefined;\n\tif (salary.pay_mask) return t('competitive');\n\n\tif (salary.pay_max && Number.isNaN(+salary.pay_max)) return t('invalid_salary');\n\tif (salary.pay_min && Number.isNaN(+salary.pay_min)) return t('invalid_salary');\n\tif (salary.pay && Number.isNaN(+salary.pay)) return t('invalid_salary');\n\n\tconst period = salary.pay_type && salary.pay_type in payPeriods ? payPeriods[salary.pay_type] : undefined;\n\n\tif (salary.pay) return [numberFormatter.format(+salary.pay), period].filter(Boolean).join(' ');\n\n\tif (salary.pay_max && salary.pay_min)\n\t\treturn [numberFormatter.formatRange(+salary.pay_min, +salary.pay_max), period].filter(Boolean).join(' ') || '';\n\n\tif (salary.pay_max)\n\t\treturn `${t('up_to')} ${[numberFormatter.format(+salary.pay_max), period].filter(Boolean).join(' ')}`;\n\tif (salary.pay_min)\n\t\treturn `${t('from')} ${[numberFormatter.format(+salary.pay_min), period].filter(Boolean).join(' ')}`;\n\treturn t('invalid_salary');\n};\n","type TFunction = (key: 'today' | 'over_30_days_ago' | 'in_over_30_days') => string;\n\ntype Params = {\n\tfrom?: Date;\n\tto: string | number | Date;\n\tformatter?: Intl.RelativeTimeFormat;\n\tt?: TFunction;\n};\n\nconst DEFAULT_FORMATTER = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' });\n/** From a date, calculates the relative time difference from now */\nexport const getRelativeTimeDifference = ({\n\tfrom = new Date(),\n\tto,\n\tformatter = DEFAULT_FORMATTER,\n\tt = s => s,\n}: Params) => {\n\tconst then = to instanceof Date ? to : new Date(to);\n\tconst diff = then.getTime() - from.getTime();\n\n\tconst diffIn = {\n\t\tdays: Math.round(diff / 1000 / 60 / 60 / 24),\n\t\tmonths: Math.round(diff / 1000 / 60 / 60 / 24 / 30),\n\t};\n\n\tif (diffIn.days === 0) return t('today');\n\tif (Math.abs(diffIn.days) < 30) return formatter.format(diffIn.days, 'days');\n\tif (Math.abs(diffIn.days) < 3) return formatter.format(diffIn.months, 'months');\n\treturn diffIn.months < 0 ? t('over_30_days_ago') : t('in_over_30_days');\n};\n","import { hasProp } from '@inploi/core/common';\nimport { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport const unauthenticatedMessage = 'Unauthenticated';\nexport const unauthorisedMessage = 'This action is unauthorized.';\n\nexport class ErrorWithStatus extends Error {\n\tpublic status?: number;\n\tconstructor(message?: string, status?: number) {\n\t\tsuper(message);\n\t\tthis.status = status;\n\t\tthis.name = 'ErrorWithStatus';\n\t}\n}\n\nexport class NotFoundError extends ErrorWithStatus {\n\tconstructor(message?: string) {\n\t\tsuper(message ?? 'Not found');\n\t\tthis.name = 'NotFoundError';\n\t\tthis.status = 404;\n\t}\n}\n\nexport class UnauthorisedError extends ErrorWithStatus {\n\tconstructor(message?: string, status?: number) {\n\t\tsuper(message ?? 'You are not authorised to perform this action.');\n\t\tthis.name = 'UnauthorisedError';\n\t\tthis.status = status ?? 401;\n\t}\n}\n\nexport class SchemaValidationError extends ErrorWithStatus {\n\tconstructor(\n\t\tpublic issues: readonly StandardSchemaV1.Issue[],\n\t\tpublic source?: 'body' | 'searchParams' | 'response',\n\t) {\n\t\tconst sourceText = source ? ` in ${source}` : '';\n\t\tsuper(`Schema validation failed${sourceText}`);\n\t\tthis.name = 'SchemaValidationError';\n\t\tthis.status = 400;\n\t}\n}\n\nexport class ApiError extends ErrorWithStatus {\n\tconstructor(message: string, status?: number) {\n\t\tsuper(message);\n\t\tthis.name = 'ApiError';\n\t\tthis.status = status ?? 500;\n\t}\n}\n\nexport class JsonParsingError extends ErrorWithStatus {\n\tconstructor(public response?: Response) {\n\t\tsuper('Error parsing response into JSON.');\n\t\tthis.name = 'ParsingError';\n\t\tthis.status = 500;\n\t}\n}\n\n/** @deprecated - use `JsonParsingError` instead */\nexport class ParsingError extends JsonParsingError {}\n\nexport type ApiClient = {\n\tfetch: (pathname: string, options?: RequestInit) => Promise<unknown>;\n};\n\nconst ERROR_MESSAGE_KEYS = ['message', 'error', 'errors', 'exception', 'exceptions'] as const;\nfunction getErrorMessageFromJson(json: unknown): string {\n\tconsole.log('json', json);\n\tconst messages: string[] = [];\n\tif (typeof json === 'object' && json !== null) {\n\t\tfor (const key of ERROR_MESSAGE_KEYS) {\n\t\t\tif (hasProp(json, key)) {\n\t\t\t\tconsole.log('hasProp', key, json[key]);\n\t\t\t\tconst value = json[key];\n\t\t\t\tif (typeof value === 'string') messages.push(value);\n\t\t\t\tif (Array.isArray(value) && value.every((item): item is string => typeof item === 'string'))\n\t\t\t\t\tmessages.push(...value);\n\t\t\t}\n\t\t}\n\t}\n\tif (messages.length === 0) messages.push('Unknown error');\n\treturn messages.join(', ');\n}\n\n/** Throws branded errors when API returns a known error. */\nexport function handleApiExceptions(json: unknown, status: number) {\n\tif (status >= 300 && status <= 500) {\n\t\tconst message = getErrorMessageFromJson(json);\n\t\tif (status === 404) {\n\t\t\tthrow new NotFoundError(message);\n\t\t}\n\t\tif (message === unauthenticatedMessage) {\n\t\t\tthrow new UnauthorisedError('You are not authenticated.', status);\n\t\t}\n\t\tif (message === unauthorisedMessage) {\n\t\t\tthrow new UnauthorisedError(message, status);\n\t\t}\n\t\tthrow new ApiError(message, status);\n\t}\n}\n\nexport const createApiClient = (params: { baseUrl: string; publishableKey: string }): ApiClient => {\n\tconst defaultHeaders: HeadersInit = {\n\t\tAccept: 'application/json',\n\t\t'Content-Type': 'application/json',\n\t\t'x-publishable-key': params.publishableKey,\n\t};\n\n\treturn {\n\t\t/** Fetches from a pathname with a pre-established base path.\n\t\t * Parses received output as JSON, and throw if one of the common error messages is received.\n\t\t */\n\t\tfetch: async (pathname, options = {}) => {\n\t\t\tconst init = { ...options, headers: { ...options.headers, ...defaultHeaders } };\n\t\t\tconst response = await fetch(`${params.baseUrl}${pathname}`, init);\n\t\t\tif (response.status === 404) throw new NotFoundError();\n\n\t\t\tconst json = await response.json().catch(async () => {\n\t\t\t\tthrow new JsonParsingError(response);\n\t\t\t});\n\n\t\t\thandleApiExceptions(json, response.status);\n\n\t\t\t// We’re assuming no other exceptions have happened.\n\t\t\treturn json;\n\t\t},\n\t};\n};\n\nexport const SdkError = {\n\tNotFound: NotFoundError,\n\tUnauthorised: UnauthorisedError,\n\tSchemaValidation: SchemaValidationError,\n\tApi: ApiError,\n\tJsonParsing: JsonParsingError,\n};\n\nexport function isSdkError(error: unknown): error is (typeof SdkError)[keyof typeof SdkError] {\n\treturn Object.values(SdkError).some(ErrorClass => error instanceof ErrorClass);\n}\n","{\n\t\"name\": \"@inploi/sdk\",\n\t\"version\": \"1.17.2\",\n\t\"main\": \"dist/index.js\",\n\t\"types\": \"dist/index.d.ts\",\n\t\"license\": \"MIT\",\n\t\"files\": [\n\t\t\"/dist\",\n\t\t\"/cdn\"\n\t],\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"require\": \"./dist/index.js\",\n\t\t\t\"import\": \"./dist/index.mjs\",\n\t\t\t\"types\": \"./dist/index.d.ts\"\n\t\t}\n\t},\n\t\"scripts\": {\n\t\t\"build:npm\": \"tsup --dts --dts-resolve\",\n\t\t\"build:cdn\": \"tsup --config tsup.cdn.config.ts\",\n\t\t\"build\": \"concurrently 'pnpm run build:npm' 'pnpm run build:cdn'\",\n\t\t\"dev\": \"tsup --watch --config tsup.cdn.config.ts\",\n\t\t\"check\": \"eslint src --fix --max-warnings 0 && tsc\",\n\t\t\"test\": \"bun test\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@happy-dom/global-registrator\": \"^13.6.2\",\n\t\t\"@inploi/core\": \"workspace:*\",\n\t\t\"@total-typescript/ts-reset\": \"^0.5.1\",\n\t\t\"@types/bun\": \"^1.2.5\",\n\t\t\"@types/react\": \"^18.2.33\",\n\t\t\"@types/react-dom\": \"^18.2.14\",\n\t\t\"autoprefixer\": \"^10.4.16\",\n\t\t\"concurrently\": \"9.1.2\",\n\t\t\"eslint\": \"^7.32.0\",\n\t\t\"eslint-config-custom\": \"workspace:*\",\n\t\t\"happy-dom\": \"^12.6.0\",\n\t\t\"ts-toolbelt\": \"^9.6.0\",\n\t\t\"tsconfig\": \"workspace:*\",\n\t\t\"tsup\": \"^7.2.0\"\n\t},\n\t\"dependencies\": {\n\t\t\"@standard-schema/spec\": \"^1.0.0\",\n\t\t\"neoqs\": \"^6.13.0\"\n\t}\n}\n","import { version } from '../package.json';\n\n/**\n * The environment the SDK should run in.\n * - `production`: data will be stored and displayed on dashboards\n * - `sandbox`: data will be stored temporarily and purged periodically\n */\nexport type InploiSdkEnvironment = 'production' | 'sandbox';\n\nexport const ENV_TO_API_URL: Record<InploiSdkEnvironment, string> = {\n\tsandbox: 'https://api.staging.inploi.com',\n\tproduction: 'https://api.inploi.com',\n\t// @ts-expect-error - local test environment\n\t_internal_local: 'http://api.test',\n};\n\nexport const ANALYTICS_VERSION = version;\n\nexport const LOG_PATHNAME = '/log';\n\nexport const ANALYTICS_COOKIE_NAME = 'isdk_session';\n","/**\n * Generates a RFC 4122 v4 UUID.\n *\n * `crypto.randomUUID()` is only available in secure contexts (HTTPS). This\n * utility falls back to `crypto.getRandomValues`, which is available in all\n * browsing contexts including HTTP, so the SDK works on non-HTTPS staging\n * environments.\n */\nexport const generateUUID = (): `${string}-${string}-${string}-${string}-${string}` => {\n\tif (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n\t\treturn crypto.randomUUID();\n\t}\n\n\treturn '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, c =>\n\t\t(+c ^ (crypto.getRandomValues(new Uint8Array(1))[0]! & (15 >> (+c / 4)))).toString(16),\n\t) as `${string}-${string}-${string}-${string}-${string}`;\n};\n","import type { ResponseObj } from '@inploi/core/common';\nimport { invariant } from '@inploi/core/common';\n\nimport { InploiRpcClient, Logger, endpoint, typed } from '.';\nimport { ANALYTICS_COOKIE_NAME, ANALYTICS_VERSION } from './sdk.constants';\nimport { generateUUID } from './sdk.uuid';\n\nconst formatCookie = (value: string) => {\n\tconst now = new Date();\n\tnow.setTime(now.getTime() + 7 * 24 * 60 * 60 * 1000); // 7 days expiration\n\n\treturn `${ANALYTICS_COOKIE_NAME}=${value};expires=${now.toUTCString()};path=/`;\n};\n\ntype FlowProperties = { flow_id: string; flow_version: number; flow_session_id: string; flow_build: number };\n\ntype JobProperties = {\n\tid: string;\n\tid_type: 'internal' | 'external';\n};\n\nexport type AnalyticsLogParams =\n\t| {\n\t\t\tevent: 'VIEW_JOB';\n\t\t\tproperties: { job: JobProperties };\n\t }\n\t| {\n\t\t\tevent: 'FLOW_REDIRECT';\n\t\t\tproperties: { href: string; job: JobProperties | undefined } & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'FLOW_START' | 'FLOW_END';\n\t\t\tproperties: { job: JobProperties | undefined } & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'FLOW_SUBMIT';\n\t\t\tproperties: {\n\t\t\t\tservice: string;\n\t\t\t\tresponse: {\n\t\t\t\t\tstatus: number;\n\t\t\t\t\tpayload: unknown;\n\t\t\t\t};\n\t\t\t\tjob: JobProperties | undefined;\n\t\t\t} & FlowProperties;\n\t }\n\t| {\n\t\t\tevent: 'SUBMIT_FORM' | 'VIEW_PAGE';\n\t\t\tproperties?: {\n\t\t\t\tjob: JobProperties | undefined;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'IDENTIFY';\n\t\t\tproperties: {\n\t\t\t\tidentifier: string;\n\t\t\t\tfirst_name?: string;\n\t\t\t\tlast_name?: string;\n\t\t\t\tphone_number?: string;\n\t\t\t\temail?: string;\n\t\t\t\tcustom_traits?: Record<string, unknown>;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_PAGINATE';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_SETTLE';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'SEARCH_JOB_CLICK';\n\t\t\tproperties: {\n\t\t\t\tjob_id: number;\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'VIEW_SEARCH';\n\t\t\tproperties: {\n\t\t\t\tquery?: string;\n\t\t\t\tfilters?: Record<string, string[]>;\n\t\t\t\tdefault_filters?: Record<string, string[]>;\n\t\t\t\ttotal_count: number;\n\t\t\t\tpage_size: number;\n\t\t\t\tpage: number;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'FEEDBACK';\n\t\t\tproperties: {\n\t\t\t\tkey: string;\n\t\t\t\tscore?: -1 | 0 | 1;\n\t\t\t\tcomment?: string;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'LINK_CLICK';\n\t\t\tproperties: {\n\t\t\t\ttarget_href: string;\n\t\t\t\tjob_id: string | undefined;\n\t\t\t};\n\t }\n\t| {\n\t\t\tevent: 'INTERACTION';\n\t\t\tproperties: {\n\t\t\t\ttag: string;\n\t\t\t};\n\t };\n\nexport type AnalyticsLogEvent = AnalyticsLogParams['event'];\n\ntype EventPropertyMap = {\n\t[Param in AnalyticsLogParams as Param['event']]: Omit<Param, 'event'>;\n};\n\ntype AnalyticsContext = {\n\tlibrary: {\n\t\tname: 'inploi-sdk';\n\t\tversion: string;\n\t};\n\tpage: {\n\t\thref: string;\n\t\treferrer: string;\n\t\ttitle: string;\n\t};\n};\n\ntype TrackPayload<P = EventPropertyMap[keyof EventPropertyMap]['properties']> = {\n\tanonymous_id: string | null;\n\tsession_id: string | null;\n\tevent: AnalyticsLogEvent;\n\tsent_at: string;\n\tcontext: AnalyticsContext;\n\tproperties: P;\n\tcustom_properties?: Record<string, unknown>;\n};\n\ntype LogFnParams<T extends keyof EventPropertyMap> = {\n\tevent: T;\n\tcustomProperties?: Record<string, unknown>;\n\t/** Passing a request will make logging possible on a server environment. */\n\trequest?: Request;\n} & EventPropertyMap[T];\n\ntype LogFn = <TEvent extends keyof EventPropertyMap>(\n\tparams: LogFnParams<TEvent>,\n) => Promise<ResponseObj<TrackPayload<EventPropertyMap[TEvent]['properties']>>>;\n\nexport type AnalyticsService = {\n\tlog: LogFn;\n\t/** From a log payload data, generate headers to use in server environments to update the anonymous_id */\n\tgetHeaders: (payload?: TrackPayload) => Headers;\n\tgetSessionInfo: typeof getSessionInfo;\n};\n\nconst getSessionId = (searchParams: URLSearchParams, isServer: boolean) => {\n\tconst fromSearchParams = searchParams.get('session_id');\n\tif (isServer) return fromSearchParams;\n\tif (fromSearchParams) return fromSearchParams;\n\tconst fromSessionStorage = sessionStorage.getItem(`${ANALYTICS_COOKIE_NAME}-session_id`);\n\tif (typeof fromSessionStorage === 'string') return fromSessionStorage;\n\treturn null;\n};\n\nconst cookieRegex = new RegExp(`${ANALYTICS_COOKIE_NAME}=([^;]+)`);\nconst getSessionInfo = (request?: Request) => {\n\tconst href = request ? request.url : location.href;\n\tconst { searchParams } = new URL(href);\n\tconst anonymous_id = searchParams.get('anonymous_id');\n\tconst session_id = getSessionId(searchParams, typeof window === 'undefined');\n\n\t// If there's an anonymous_id in the search params, use it\n\tif (anonymous_id)\n\t\treturn {\n\t\t\tanonymous_id,\n\t\t\tsession_id,\n\t\t};\n\n\t// If there's a cookie, use it\n\tconst cookie = request ? request.headers.get('cookie') : document.cookie;\n\tif (cookie) {\n\t\tconst match = cookieRegex.exec(cookie);\n\t\tconst anonymous_id = match?.[1];\n\t\treturn {\n\t\t\tanonymous_id: anonymous_id ?? null,\n\t\t\tsession_id,\n\t\t};\n\t}\n\n\t// Otherwise, return what we have\n\treturn {\n\t\tanonymous_id,\n\t\tsession_id,\n\t};\n};\n\n/**\n * Get or create a persistent anonymous ID.\n *\n * This is the universal identifier that bridges:\n * - SDK analytics (Laravel tracking)\n * - Agent conversations (Durable Object routing)\n * - Identity resolution\n *\n * The ID is:\n * - Generated client-side if none exists\n * - Persisted in cookie for 7 days\n * - The same across all SDK plugins\n *\n * @returns The anonymous ID (existing or newly generated)\n */\nexport const getOrCreateAnonymousId = (): string => {\n\t// Server-side: cannot generate, return empty (should not happen in normal flow)\n\tif (typeof window === 'undefined') {\n\t\tthrow new Error('getOrCreateAnonymousId() can only be called in browser environment');\n\t}\n\n\t// Check existing sources first\n\tconst existing = getSessionInfo().anonymous_id;\n\tif (existing) return existing;\n\n\t// Generate new ID and immediately persist to cookie\n\tconst newId = generateUUID();\n\tdocument.cookie = formatCookie(newId);\n\treturn newId;\n};\n\nconst getSessionInfoFromResponse = (response: unknown) => {\n\tif (typeof response !== 'object' || response === null) return null;\n\treturn {\n\t\tanonymous_id:\n\t\t\t'anonymous_id' in response && typeof response.anonymous_id === 'string' ? response.anonymous_id : null,\n\t\tsession_id: 'session_id' in response && typeof response.session_id === 'string' ? response.session_id : null,\n\t};\n};\n\nconst serverReferrer = (referrer: typeof Request.prototype.referrer) => {\n\tif (referrer === 'about:client') return '';\n\treturn referrer;\n};\n\nconst analyticsLogEndpoint = endpoint({\n\tpathname: '/log',\n\tmethod: 'POST',\n\tschema: {\n\t\tresponse: typed<unknown>(),\n\t\tbody: typed<TrackPayload>(),\n\t},\n});\n\nexport type AnalyticsOnEventCallback = (event: AnalyticsLogParams) => void;\n\nexport const createAnalyticsService = ({\n\trpcClient,\n\tlogger,\n\tonEvent,\n}: {\n\tlogger: Logger;\n\trpcClient: InploiRpcClient;\n\tonEvent?: AnalyticsOnEventCallback;\n}): AnalyticsService => {\n\tconst logFn: LogFn = async params => {\n\t\tinvariant(\n\t\t\tparams.request || typeof window !== 'undefined',\n\t\t\t'Cannot log on the server without a request. Please pass a request to `log`.',\n\t\t);\n\n\t\t// if there’s a request, use it instead of browser APIs\n\t\tconst page =\n\t\t\t'request' in params && params.request ?\n\t\t\t\t{\n\t\t\t\t\thref: params.request.url,\n\t\t\t\t\treferrer: serverReferrer(params.request.referrer),\n\t\t\t\t\ttitle: '',\n\t\t\t\t}\n\t\t\t:\t{\n\t\t\t\t\thref: location.href,\n\t\t\t\t\treferrer: document.referrer,\n\t\t\t\t\ttitle: document.title,\n\t\t\t\t};\n\n\t\ttry {\n\t\t\tconst context: AnalyticsContext = {\n\t\t\t\tlibrary: {\n\t\t\t\t\tname: 'inploi-sdk',\n\t\t\t\t\tversion: ANALYTICS_VERSION,\n\t\t\t\t},\n\t\t\t\tpage,\n\t\t\t};\n\n\t\t\tconst sessionInfo = getSessionInfo(params.request);\n\t\t\tconst payload: TrackPayload = {\n\t\t\t\tanonymous_id: sessionInfo.anonymous_id,\n\t\t\t\tsession_id: sessionInfo.session_id,\n\t\t\t\tevent: params.event,\n\t\t\t\tsent_at: new Date().toISOString(),\n\t\t\t\tcontext,\n\t\t\t\tproperties: params.properties,\n\t\t\t\tcustom_properties: params.customProperties,\n\t\t\t};\n\n\t\t\tconst responseJson = await rpcClient.request(analyticsLogEndpoint, {\n\t\t\t\tbody: payload,\n\t\t\t});\n\n\t\t\tconst newSession = getSessionInfoFromResponse(responseJson);\n\t\t\tif (newSession?.anonymous_id) {\n\t\t\t\tpayload.anonymous_id = newSession.anonymous_id;\n\t\t\t}\n\t\t\tif (newSession?.session_id) {\n\t\t\t\tpayload.session_id = newSession.session_id;\n\t\t\t}\n\n\t\t\tif (typeof window !== 'undefined' && payload.anonymous_id) {\n\t\t\t\tif (payload.session_id) {\n\t\t\t\t\tsessionStorage.setItem(`${ANALYTICS_COOKIE_NAME}-session_id`, payload.session_id.toString());\n\t\t\t\t}\n\t\t\t\tdocument.cookie = formatCookie(payload.anonymous_id);\n\t\t\t}\n\n\t\t\tonEvent?.(payload as AnalyticsLogParams);\n\t\t\treturn { success: true, data: payload };\n\t\t} catch (e) {\n\t\t\t/** We dont’t log any PII on the console */\n\t\t\tlogger.error('Failed to send log to API. Inspect error response of `log` for more information.');\n\t\t\treturn { success: false, error: e };\n\t\t}\n\t};\n\n\treturn {\n\t\tlog: logFn,\n\t\tgetHeaders: payload => {\n\t\t\tconst headers = new Headers();\n\t\t\tif (!payload?.anonymous_id) return headers;\n\n\t\t\theaders.append('Set-Cookie', formatCookie(payload.anonymous_id));\n\t\t\treturn headers;\n\t\t},\n\t\tgetSessionInfo,\n\t};\n};\n","import type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { stringify } from 'neoqs';\n\nimport { JsonParsingError, SchemaValidationError, handleApiExceptions } from './sdk.api';\nimport { ENV_TO_API_URL, InploiSdkEnvironment } from './sdk.constants';\nimport { Logger } from './sdk.logger';\n\ntype RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\n\n/** Extract parameter names from a pathname string */\ntype ExtractParamNames<T extends string> =\n\tT extends `${infer _Before}:${infer Param}/${infer After}` ? Param | ExtractParamNames<`/${After}`>\n\t: T extends `${infer _Before}:${infer Param}` ? Param\n\t: never;\n\n/** Create params object from parameter names */\ntype ExtractPathParams<T extends string> =\n\tstring extends T ? Record<string, string | number>\n\t: ExtractParamNames<T> extends never ? Record<string, never>\n\t: { [K in ExtractParamNames<T>]: string | number };\n\n/** Parses a StandardSchemaV1 schema and input into an output. */\nexport function parse<T extends StandardSchemaV1>(\n\tschema: T,\n\tinput: StandardSchemaV1.InferInput<T>,\n\tsource?: 'body' | 'searchParams' | 'response',\n): StandardSchemaV1.InferOutput<T> {\n\tconst result = schema['~standard'].validate(input);\n\tif (result instanceof Promise) {\n\t\tthrow new TypeError('Async schema');\n\t}\n\n\tif (result.issues) {\n\t\tthrow new SchemaValidationError(result.issues, source);\n\t}\n\n\treturn result.value;\n}\n\n/** Parses a StandardSchemaV1 schema and input into an output, returning a success flag and issues if the parse fails. */\nexport function safeParse<T extends StandardSchemaV1>(\n\tschema: T,\n\tinput: StandardSchemaV1.InferInput<T>,\n\tsource?: 'body' | 'searchParams' | 'response',\n):\n\t| {\n\t\t\tsuccess: true;\n\t\t\toutput: StandardSchemaV1.InferOutput<T>;\n\t }\n\t| {\n\t\t\tsuccess: false;\n\t\t\tissues: readonly StandardSchemaV1.Issue[];\n\t\t\tsource?: 'body' | 'searchParams' | 'response';\n\t } {\n\ttry {\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\toutput: parse(schema, input, source),\n\t\t};\n\t} catch (e) {\n\t\tif (e instanceof SchemaValidationError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tissues: e.issues,\n\t\t\t\tsource: e.source,\n\t\t\t};\n\t\t}\n\t\tthrow e;\n\t}\n}\n\nexport interface InploiRpcClientParams {\n\tenvironment: InploiSdkEnvironment;\n\tlogger: Logger;\n\tapiKey:\n\t\t| {\n\t\t\t\t/** Makes the API call with an x-secret-key header\n\t\t\t\t * This will error if used in a browser environment.\n\t\t\t\t */\n\t\t\t\ttype: 'secret';\n\t\t\t\tkey: string;\n\t\t }\n\t\t| {\n\t\t\t\t/** Makes the API call with an x-publishable-key header\n\t\t\t\t * This can be called in a browser or server environment.\n\t\t\t\t */\n\t\t\t\ttype: 'publishable';\n\t\t\t\tkey: string;\n\t\t };\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\ntype NonReducibleUnknown = {} | null | undefined;\ntype LooseAutocomplete<T extends BaseType, BaseType> = T | BaseType;\n\n/** RPC client for making API calls to the Inploi API. */\nexport class InploiRpcClient {\n\tprivate baseUrl: string;\n\tprivate headers: Headers;\n\tprivate logger: Logger;\n\tprivate _environment: InploiSdkEnvironment;\n\n\tconstructor(params: InploiRpcClientParams) {\n\t\tthis.baseUrl = ENV_TO_API_URL[params.environment];\n\t\tthis.headers = new Headers({\n\t\t\t'Content-Type': 'application/json',\n\t\t\tAccept: 'application/json',\n\t\t});\n\t\tif (params.apiKey.type === 'secret') {\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\tthrow new Error('Secret key cannot be used in a browser environment');\n\t\t\t}\n\t\t\tthis.headers.set('x-secret-key', params.apiKey.key);\n\t\t} else {\n\t\t\tthis.headers.set('x-publishable-key', params.apiKey.key);\n\t\t}\n\t\tthis.logger = params.logger;\n\t\tthis._environment = params.environment;\n\t}\n\n\tget environment() {\n\t\treturn this._environment;\n\t}\n\n\t/** Gets params for a fetch request to the given endpoint */\n\tgetFetchParams<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: T extends RpcEndpoint<infer _, infer _TPathname, infer TPathParams, infer TSearch, infer TBody> ?\n\t\t\tGetSchemaValues<{\n\t\t\t\tbody: TBody;\n\t\t\t\tsearchParams: TSearch;\n\t\t\t\tparams: TPathParams;\n\t\t\t}> & {\n\t\t\t\tsignal?: AbortSignal;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the inputs against the schema.\n\t\t\t\t * If you want to skip validation (e.g.: already validated yourself or with `validateEndpontInputs`), set this to false.\n\t\t\t\t */\n\t\t\t\tvalidateIn?: boolean;\n\t\t\t}\n\t\t:\tnever,\n\t): [url: string, options: RequestInit] {\n\t\tconst validateIn = options.validateIn ?? true;\n\t\tconst { searchParams, body } = validateIn ? validateEndpointInputs(endpoint, options) : options;\n\n\t\tconst url = new URL(this.baseUrl);\n\n\t\t// Replace path parameters in pathname\n\t\tlet pathname = endpoint.pathname;\n\t\tif ('params' in options && options.params) {\n\t\t\tfor (const [key, value] of Object.entries(options.params)) {\n\t\t\t\tpathname = pathname.replace(`:${key}`, String(value));\n\t\t\t}\n\t\t}\n\t\turl.pathname = pathname;\n\n\t\tif (endpoint.schema.searchParams) {\n\t\t\turl.search = stringify(searchParams);\n\t\t}\n\n\t\treturn [\n\t\t\turl.toString(),\n\t\t\t{\n\t\t\t\tmethod: endpoint.method,\n\t\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t\t\theaders: this.headers,\n\t\t\t\tsignal: options.signal,\n\t\t\t},\n\t\t];\n\t}\n\n\t/** Parses a response against an endpoint’s response schema, considering common errors thrown from the API.\n\t * @throws {JsonParsingError} - If the response is not valid JSON.\n\t * @throws {SchemaValidationError} - If the response does not match the schema.\n\t * @throws {ApiError} - If the API responded with an error message.\n\t */\n\tasync parseResponse<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: {\n\t\t\tresponse: Response;\n\t\t\t/**\n\t\t\t * Whether to validate the response against the schema.\n\t\t\t * This is meant more as an escape hatch for when the response is not as expected and you want to handle it separately yourself.\n\t\t\t * ⚠️ This will lead to potential type/runtime mismatch as it does not verify the response against the schema.\n\t\t\t */\n\t\t\tvalidateOut?: boolean;\n\t\t},\n\t): Promise<StandardSchemaV1.InferOutput<T['schema']['response']>> {\n\t\tconst json = await options.response.json().catch(e => {\n\t\t\tthis.logger.error(e);\n\t\t\tthrow new JsonParsingError(options.response);\n\t\t});\n\n\t\tconst validateOut = options.validateOut ?? true;\n\t\tif (!validateOut) return json as StandardSchemaV1.InferOutput<T['schema']['response']>;\n\n\t\tconst result = safeParse(endpoint.schema.response, json, 'response');\n\t\tif (!result.success) {\n\t\t\thandleApiExceptions(json, options.response.status);\n\t\t\tthrow new SchemaValidationError(result.issues, result.source);\n\t\t}\n\n\t\treturn result.output as StandardSchemaV1.InferOutput<T['schema']['response']>;\n\t}\n\n\t/** Fetches, parses and validates an API endpoint.\n\t * Logs errors and throws them again so that the caller can handle them.\n\t *\n\t * @throws {JsonParsingError} - If the response is not valid JSON.\n\t * @throws {SchemaValidationError} - If the searchParams, body or response does not match the schema.\n\t * @throws {ApiError} - If the API responded with an error message.\n\t * @throws {UnauthorisedError} - If the request is unauthorised either by missing key or unmet permissions.\n\t * @throws {NotFoundError} - If the endpoint is not found.\n\t * @throws {Error} - Another unhandled error.\n\t */\n\tasync request<T extends RpcEndpoint>(\n\t\tendpoint: T,\n\t\toptions: T extends RpcEndpoint<infer _, infer _TPathname, infer TPathParams, infer TSearch, infer TBody> ?\n\t\t\tGetSchemaValues<{\n\t\t\t\tbody: TBody;\n\t\t\t\tsearchParams: TSearch;\n\t\t\t\tparams: TPathParams;\n\t\t\t}> & {\n\t\t\t\tsignal?: AbortSignal;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the inputs against the schema.\n\t\t\t\t * If you want to skip validation (e.g.: already validated yourself or with `validateEndpontInputs`), set this to false.\n\t\t\t\t */\n\t\t\t\tvalidateIn?: boolean;\n\t\t\t\t/**\n\t\t\t\t * Whether to validate the response against the schema.\n\t\t\t\t * This is meant more as an escape hatch for when the response is not as expected and you want to handle it separately yourself.\n\t\t\t\t * ⚠️ This will lead to potential type/runtime mismatch as it does not verify the response against the schema.\n\t\t\t\t */\n\t\t\t\tvalidateOut?: boolean;\n\t\t\t}\n\t\t:\tnever,\n\t): Promise<StandardSchemaV1.InferOutput<T['schema']['response']>> {\n\t\ttry {\n\t\t\tconst fetchParams = this.getFetchParams(endpoint, options);\n\t\t\tconst response = await fetch(...fetchParams);\n\t\t\treturn this.parseResponse(endpoint, { response, validateOut: options.validateOut });\n\t\t} catch (e) {\n\t\t\tif (e instanceof SchemaValidationError) {\n\t\t\t\tthis.logger.error(e.message, e.issues);\n\t\t\t} else {\n\t\t\t\tthis.logger.error(e);\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t}\n}\n\ntype GetSchemaValues<T extends { searchParams: any; body: any; params?: any }> = {\n\t[K in keyof T as T[K] extends never ? never\n\t: T[K] extends Record<string, never> ? never\n\t: K]: T[K] extends never ? never : LooseAutocomplete<T[K], NonReducibleUnknown>;\n};\n\n/**\n * Typed but *not runtime validated* schema\n * useful for type-checking the schema without bundling validation schemas\n */\nexport function typed<T>(): StandardSchemaV1<T, T> {\n\treturn {\n\t\t'~standard': {\n\t\t\tvendor: 'inploi',\n\t\t\tversion: 1,\n\t\t\tvalidate: input => {\n\t\t\t\treturn {\n\t\t\t\t\tvalue: input as T,\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t};\n}\n\nexport interface RpcEndpoint<\n\tTMethod extends RequestMethod = RequestMethod,\n\tTPathname extends string = string,\n\tTPathParams = any,\n\tTSearch = any,\n\tTBody = any,\n\tTResponse = any,\n> {\n\tpathname: TPathname;\n\tmethod: TMethod;\n\theaders?: Headers;\n\tschema: {\n\t\tsearchParams?: StandardSchemaV1<TSearch, TSearch>;\n\t\tbody?: StandardSchemaV1<TBody, TBody>;\n\t\tresponse: StandardSchemaV1<TResponse, TResponse>;\n\t};\n\t/** Type-only property to store path parameter types */\n\treadonly __pathParams?: TPathParams;\n}\n\nexport function endpoint<\n\tTMethod extends RequestMethod,\n\tTPathname extends string,\n\tTSearch extends StandardSchemaV1 | never = never,\n\tTBody extends StandardSchemaV1 | never = never,\n\tTResponse extends StandardSchemaV1 | never = never,\n>(endpoint: {\n\tpathname: TPathname;\n\tmethod: TMethod;\n\theaders?: Headers;\n\tschema: {\n\t\tsearchParams?: TSearch;\n\t\tbody?: TBody;\n\t\tresponse: TResponse;\n\t};\n}) {\n\ttype PathParams = ExtractPathParams<TPathname>;\n\treturn endpoint as RpcEndpoint<\n\t\tTMethod,\n\t\tTPathname,\n\t\tPathParams,\n\t\tStandardSchemaV1.InferInput<TSearch>,\n\t\tStandardSchemaV1.InferInput<TBody>,\n\t\tStandardSchemaV1.InferOutput<TResponse>\n\t>;\n}\n\n/** Validates the inputs for an endpoint ahead of time\n * Useful when you need to validate and throw earlier, or use the inputs for something other than the API call.\n */\nexport function validateEndpointInputs<T extends RpcEndpoint>(\n\tendpoint: T,\n\toptions: GetSchemaValues<{ body: unknown; searchParams: unknown }>,\n) {\n\tconst validatedInputs = {\n\t\tsearchParams: undefined,\n\t\tbody: undefined,\n\t\tvalidateIn: false,\n\t} as T extends RpcEndpoint<infer _, infer __, infer ___, infer TSearch, infer TBody> ?\n\t\tGetSchemaValues<{\n\t\t\tbody: TBody;\n\t\t\tsearchParams: TSearch;\n\t\t}> & {\n\t\t\tvalidateIn: false;\n\t\t}\n\t:\tnever;\n\n\tif (endpoint.schema.searchParams) {\n\t\tvalidatedInputs.searchParams = parse(\n\t\t\tendpoint.schema.searchParams,\n\t\t\t'searchParams' in options ? options.searchParams : {},\n\t\t);\n\t}\n\n\tif (endpoint.schema.body) {\n\t\tvalidatedInputs.body = parse(endpoint.schema.body, 'body' in options ? options.body : {});\n\t}\n\n\treturn validatedInputs;\n}\n","import { AnalyticsOnEventCallback, createAnalyticsService } from './sdk.analytics';\nimport { createApiClient } from './sdk.api';\nimport { ENV_TO_API_URL, InploiSdkEnvironment } from './sdk.constants';\nimport { Logger, inploiBrandedLogger, noLogging } from './sdk.logger';\nimport { InploiSdkPlugin } from './sdk.plugins';\nimport { InploiRpcClient } from './sdk.rpc';\n\nexport type InitialiseInploiSdkParams = {\n\t/** Your public API key for the inploi SDK. */\n\tpublishableKey: string;\n\t/** Which app environment to run. This ultimately affects which inploi endpoints to gather data are going to be used.\n\t * Anything other than `production` should be considered a development environment and the data periodicaly purged. */\n\tenv: InploiSdkEnvironment;\n\t/** Logger object that handles logging of different levels.\n\t * You can override this to use your own logger, or to disable logging altogether by passing`false`.\n\t * @default inploiBrandedLogger\n\t * */\n\tlogger?: Logger | false;\n\n\t/** When provided, this callback will be called with every event that is logged to the analytics service. */\n\tonEvent?: AnalyticsOnEventCallback;\n};\n\nexport function initialiseSdk({\n\tpublishableKey,\n\tenv,\n\tlogger = inploiBrandedLogger,\n\tonEvent,\n}: InitialiseInploiSdkParams) {\n\t/** @deprecated - use `rpcClient` instead */\n\tconst apiClient = createApiClient({ baseUrl: ENV_TO_API_URL[env], publishableKey });\n\tconst loggerService = logger === false ? noLogging : logger;\n\tconst rpcClient = new InploiRpcClient({\n\t\tenvironment: env,\n\t\tapiKey: { type: 'publishable', key: publishableKey },\n\t\tlogger: loggerService,\n\t});\n\tconst analytics = createAnalyticsService({ rpcClient, logger: loggerService, onEvent });\n\n\tconst register = <P extends InploiSdkPlugin>(plugin: P): ReturnType<P> => {\n\t\treturn plugin({ logger: loggerService, apiClient, analytics, rpcClient, publishableKey, env });\n\t};\n\n\treturn { register, analytics, apiClient };\n}\n\nexport type InploiSdk = ReturnType<typeof initialiseSdk>;\n"],"mappings":"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","names":["CONSOLE_PREFIX","CONSOLE_STYLE","inploiBrandedLogger","args","noLogging","createPlugin","pluginFn","invariant","condition","message","hasProp","data","prop","DEFAULT_FORMATTER","unauthenticatedMessage","unauthorisedMessage","ErrorWithStatus","message","status","NotFoundError","UnauthorisedError","SchemaValidationError","issues","source","sourceText","ApiError","JsonParsingError","response","ERROR_MESSAGE_KEYS","getErrorMessageFromJson","json","messages","key","hasProp","value","item","handleApiExceptions","status","message","NotFoundError","unauthenticatedMessage","UnauthorisedError","unauthorisedMessage","ApiError","createApiClient","params","defaultHeaders","pathname","options","init","response","JsonParsingError","SdkError","SchemaValidationError","isSdkError","error","ErrorClass","version","ENV_TO_API_URL","ANALYTICS_VERSION","version","ANALYTICS_COOKIE_NAME","generateUUID","c","formatCookie","value","now","ANALYTICS_COOKIE_NAME","getSessionId","searchParams","isServer","fromSearchParams","fromSessionStorage","cookieRegex","getSessionInfo","request","href","anonymous_id","session_id","cookie","getOrCreateAnonymousId","existing","newId","generateUUID","getSessionInfoFromResponse","response","serverReferrer","referrer","analyticsLogEndpoint","typed","createAnalyticsService","rpcClient","logger","onEvent","params","invariant","page","context","ANALYTICS_VERSION","sessionInfo","payload","responseJson","newSession","e","headers","stringify","parse","schema","input","source","result","SchemaValidationError","safeParse","e","InploiRpcClient","params","ENV_TO_API_URL","endpoint","options","validateIn","searchParams","body","validateEndpointInputs","url","pathname","key","value","stringify","json","JsonParsingError","handleApiExceptions","fetchParams","response","typed","validatedInputs","initialiseSdk","publishableKey","env","logger","inploiBrandedLogger","onEvent","apiClient","createApiClient","ENV_TO_API_URL","loggerService","noLogging","rpcClient","InploiRpcClient","analytics","createAnalyticsService","plugin"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inploi/sdk",
3
- "version": "1.17.0",
3
+ "version": "1.17.2",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "MIT",
@@ -27,7 +27,7 @@
27
27
  "happy-dom": "^12.6.0",
28
28
  "ts-toolbelt": "^9.6.0",
29
29
  "tsup": "^7.2.0",
30
- "@inploi/core": "1.16.1",
30
+ "@inploi/core": "1.16.2",
31
31
  "eslint-config-custom": "0.1.0",
32
32
  "tsconfig": "0.1.0"
33
33
  },