collectlie
Version:
TypeScript SDK for Collectlie - flexible data collection platform with custom types, schema validation, and Supabase backend integration
2 lines (1 loc) • 19.1 kB
JavaScript
;Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@supabase/supabase-js"),t="undefined"!=typeof document?document.currentScript:null;class n extends Error{constructor(e,t,o,r,i,s){super(e),this.name="CollectlieError",this.status=t,this.code=o,this.details=r,this.debugInfo=i,this.upgradeRequired=s,Error.captureStackTrace&&Error.captureStackTrace(this,n)}toDetailedString(){let e=`${this.name} (${this.status}): ${this.message}`;if(this.details){e+=`\nDetails: ${Array.isArray(this.details)?this.details.join(", "):this.details}`}return this.upgradeRequired&&(e+="\nPlan upgrade required"),this.debugInfo&&(e+=`\nDebug: ${JSON.stringify(this.debugInfo,null,2)}`),e}}class o extends n{constructor(e,t,n){super(e,400,"VALIDATION_ERROR",t,n),this.name="ValidationError"}}class r extends n{constructor(e,t,n,o){super(e,403,"AUTHENTICATION_ERROR",t,n,o),this.name="AuthenticationError"}}class i extends n{constructor(e,t,n){super(e,413,"PAYLOAD_TOO_LARGE",t,n),this.name="PayloadTooLargeError"}}class s extends n{constructor(e,t,n,o){super(e,429,"RATE_LIMIT_ERROR",t,n),this.name="RateLimitError",o&&(this.resetAt=new Date(o))}}class a extends n{constructor(e,t=500,n,o){super(e,t,"SERVER_ERROR",n,o),this.name="ServerError"}}class c extends n{constructor(e,t){super(e,0,"NETWORK_ERROR",void 0,t?{originalMessage:t.message,originalStack:t.stack}:void 0),this.name="NetworkError"}}class d extends n{constructor(e,t){super(e,0,"CONFIGURATION_ERROR",t),this.name="ConfigurationError"}}function l(e,t){const c=t.error||t.message||`HTTP ${e} error`,d=t.details,l=t.debug_info,u=t.upgrade_required;switch(e){case 400:return new o(c,d,l);case 403:return new r(c,d,l,u);case 413:return new i(c,d,l);case 429:return new s(c,d,l);case 500:case 502:case 503:case 504:return new a(c,e,d,l);default:return new n(c,e,"UNKNOWN_ERROR",d,l,u)}}class u{constructor(e){this.config={baseUrl:"https://mmnnfybraewpuvttamvb.supabase.co/functions/v1",validateSchemas:!0,...e}}async makeRequest(e){const{method:t,endpoint:n,data:o,headers:r={},authRequired:i=!1}=e,s=`${this.config.baseUrl}${n}`,a={"Content-Type":"application/json",...r};try{const e=await fetch(s,{method:t,headers:a,body:o?JSON.stringify(o):void 0});let n;try{n=await e.json()}catch{n=null}if(!e.ok){const t=n;throw l(e.status,t||{error:`HTTP ${e.status}: ${e.statusText}`})}return n}catch(e){if(e&&"object"==typeof e&&"status"in e)throw e;if(e instanceof Error)throw new c(e.message||"Network request failed",e);throw new c("Unknown error occurred")}}async submitSubmission(t){const n=e.createClient("https://mmnnfybraewpuvttamvb.supabase.co","eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im1tbm5meWJyYWV3cHV2dHRhbXZiIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTU2MzUwMTUsImV4cCI6MjA3MTIxMTAxNX0.915hb2NCk8CV-ZEurWBlB49KxwrLwwhGeDPWSafS7kE"),{data:o,error:r}=await n.functions.invoke("submit-submission",{body:t});if(r){if(r.status)throw l(r.status,{error:r.message||"Edge function call failed"});throw new c(r.message||"Edge function call failed")}return o}async submitWithFiles(e){const t=new FormData,n=[...e.attachments||[]],o={...e};o.attachments&&(o.attachments=n.map(e=>({filename:e.filename,mimeType:e.mimeType,size:e.size}))),t.append("data",JSON.stringify(o)),n.forEach((e,n)=>{if(e.data){const o=`attachment_${n}`;t.append(o,e.data,e.filename)}});const r=`${this.config.baseUrl}/submit-submission`,i=await fetch(r,{method:"POST",body:t,headers:{Authorization:"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im1tbm5meWJyYWV3cHV2dHRhbXZiIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTU2MzUwMTUsImV4cCI6MjA3MTIxMTAxNX0.915hb2NCk8CV-ZEurWBlB49KxwrLwwhGeDPWSafS7kE"}});if(!i.ok){let e=null;try{e=await i.json()}catch{e={error:`HTTP ${i.status}: ${i.statusText}`}}throw l(i.status,e||{error:`HTTP ${i.status}: ${i.statusText}`})}return await i.json()}hasFilesToUpload(e){return e.attachments?.some(e=>null!=e.data)??!1}}function p(e,t={}){const n=[];if(e.project_id&&"string"==typeof e.project_id||n.push("project_id is required and must be a string"),e.type&&"string"==typeof e.type||n.push("type is required and must be a string"),void 0!==e.title&&"string"!=typeof e.title&&n.push("title must be a string"),void 0!==e.content&&"string"!=typeof e.content&&n.push("content must be a string"),void 0!==e.author)if("object"!=typeof e.author||null===e.author)n.push("author must be an object");else{const t=function(e){const t=[];void 0!==e.email&&"string"!=typeof e.email&&t.push("author.email must be a string");void 0!==e.name&&"string"!=typeof e.name&&t.push("author.name must be a string");void 0!==e.avatar&&"string"!=typeof e.avatar&&t.push("author.avatar must be a string");void 0!==e.userId&&"string"!=typeof e.userId&&t.push("author.userId must be a string");void 0!==e.username&&"string"!=typeof e.username&&t.push("author.username must be a string");return t}(e.author);n.push(...t)}if(void 0!==e.attachments)if(Array.isArray(e.attachments)){const o=function(e){const t=[];return e.forEach((e,n)=>{e.filename&&"string"==typeof e.filename||t.push(`Attachment ${n+1}: filename is required and must be a string`),e.data&&(e.data instanceof File||e.data instanceof Blob?(!e.mimeType&&e.data.type&&(e.mimeType=e.data.type),e.size||(e.size=e.data.size)):t.push(`Attachment ${n+1}: data must be a File or Blob object`)),e.url&&"string"!=typeof e.url&&t.push(`Attachment ${n+1}: url must be a string`),e.data||e.url||t.push(`Attachment ${n+1}: must have either data (for upload) or url (if pre-uploaded)`)}),t}(e.attachments,t);n.push(...o)}else n.push("attachments must be an array");if(void 0!==e.tags){const t=function(e){const t=[];"string"==typeof e?0===e.length&&t.push("tag cannot be empty"):Array.isArray(e)?e.forEach((e,n)=>{"string"!=typeof e?t.push(`tag at index ${n} must be a string`):0===e.length&&t.push(`tag at index ${n} cannot be empty`)}):t.push("tags must be a string or array of strings");return t}(e.tags);n.push(...t)}return n}function h(e){const t={};if("undefined"==typeof window)return t;const n=e||{url:!0,path:!0,title:!0,search:!0,hash:!0,host:!0,referrer:!0};try{window.location&&(n.url&&(t.url=window.location.href),n.path&&(t.path=window.location.pathname),n.search&&window.location.search&&(t.search=window.location.search),n.hash&&window.location.hash&&(t.hash=window.location.hash),n.host&&(t.host=window.location.host)),n.title&&document.title&&(t.title=document.title),n.referrer&&document.referrer&&(t.referrer=document.referrer)}catch(e){}return t}function m(e){const t={};if("undefined"==typeof window)return t;const n=e||{viewport:!0,screen:!0,language:!0,languages:!0,timezone:!0,cookiesEnabled:!0,localStorageAvailable:!0,sessionStorageAvailable:!0};try{if(n.viewport&&window.innerWidth&&window.innerHeight&&(t.viewport={width:window.innerWidth,height:window.innerHeight}),n.screen&&window.screen&&(t.screen={width:window.screen.width,height:window.screen.height,colorDepth:window.screen.colorDepth||24}),n.language&&navigator.language&&(t.language=navigator.language),n.languages&&navigator.languages&&navigator.languages.length>0&&(t.languages=Array.from(navigator.languages)),n.timezone)try{t.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{const e=(new Date).getTimezoneOffset();t.timezone=`UTC${e>0?"-":"+"}${Math.abs(e/60)}`}if(n.cookiesEnabled&&(t.cookiesEnabled=navigator.cookieEnabled),n.localStorageAvailable)try{localStorage.setItem("test","test"),localStorage.removeItem("test"),t.localStorageAvailable=!0}catch{t.localStorageAvailable=!1}if(n.sessionStorageAvailable)try{sessionStorage.setItem("test","test"),sessionStorage.removeItem("test"),t.sessionStorageAvailable=!0}catch{t.sessionStorageAvailable=!1}}catch(e){}return t}function f(e){const t={};if("undefined"==typeof window||"undefined"==typeof navigator)return t;const n=e||{deviceType:!0,touchSupport:!0,pixelRatio:!0};try{if(n.deviceType){const e=navigator.userAgent.toLowerCase(),n=/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(e),o=/ipad|android(?=.*\bmobile\b)/i.test(e)||window.screen&&window.screen.width>=768&&window.screen.width<=1024;t.deviceType=n&&!o?"mobile":o?"tablet":"desktop"}n.touchSupport&&(t.touchSupport="ontouchstart"in window||navigator.maxTouchPoints>0),n.pixelRatio&&window.devicePixelRatio&&(t.pixelRatio=window.devicePixelRatio)}catch(e){}return t}function g(e){const t={};if("undefined"==typeof window)return t;const n=e||{errorCount:!0,recentErrors:!0,failedResources:!0};try{if(window.console&&window.console.__errors){const e=window.console.__errors||[];n.errorCount&&(t.error_count=e.length),n.recentErrors&&(t.recent_errors=e.slice(-5).map(e=>{return{message:(t=e.message||"Unknown error",t.replace(/\/[^\/\s]+\.(js|ts|jsx|tsx)/g,"[file]").replace(/https?:\/\/[^\s]+/g,"[url]").replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,"[email]").replace(/\b\d{4,}\b/g,"[number]").replace(/['"].*?['"]/g,"[string]").substring(0,200)),timestamp:e.timestamp||Date.now(),type:e.type||"error"};var t}))}if(n.failedResources){const e={};if(window.performance&&window.performance.getEntriesByType){window.performance.getEntriesByType("resource").forEach(t=>{if(0===t.responseStatus||t.responseStatus>=400){const n=t.name.split(".").pop()?.split("?")[0]||"unknown";e[n]=(e[n]||0)+1}}),t.failed_resources=Object.entries(e).map(([e,t])=>({type:e,count:t}))}}}catch(e){}return t}function w(e){const t={};if("undefined"==typeof window||"undefined"==typeof navigator)return t;const n=e||{online:!0,connection:!0,colorScheme:!0,reducedMotion:!0,contrast:!0,transparency:!0,invertedColors:!0,monochrome:!0,forcedColors:!0,storage:!0,permissions:!0};try{if(n.online&&(t.online=navigator.onLine),n.connection&&"connection"in navigator){const e=navigator.connection;e&&(t.connection={type:e.type,effective_type:e.effectiveType,downlink:e.downlink,rtt:e.rtt,save_data:e.saveData})}if(window.matchMedia&&(n.colorScheme&&(window.matchMedia("(prefers-color-scheme: dark)").matches?t.color_scheme="dark":window.matchMedia("(prefers-color-scheme: light)").matches?t.color_scheme="light":t.color_scheme="no-preference"),n.reducedMotion&&(t.reduced_motion=window.matchMedia("(prefers-reduced-motion: reduce)").matches),n.contrast&&(window.matchMedia("(prefers-contrast: high)").matches?t.contrast="high":window.matchMedia("(prefers-contrast: low)").matches?t.contrast="low":t.contrast="no-preference"),n.transparency&&(t.transparency=window.matchMedia("(prefers-reduced-transparency: reduce)").matches?"reduce":"no-preference"),n.invertedColors&&(t.inverted_colors=window.matchMedia("(inverted-colors: inverted)").matches),n.forcedColors&&(t.forced_colors=window.matchMedia("(forced-colors: active)").matches),n.monochrome)){const e=window.matchMedia("(monochrome)");t.monochrome=e.matches?1:0}if(n.storage){t.storage={cookies_enabled:navigator.cookieEnabled,local_storage:!1,session_storage:!1,indexed_db:!1};try{localStorage.setItem("test","test"),localStorage.removeItem("test"),t.storage.local_storage=!0}catch{}try{sessionStorage.setItem("test","test"),sessionStorage.removeItem("test"),t.storage.session_storage=!0}catch{}"indexedDB"in window&&(t.storage.indexed_db=!0)}n.permissions&&"permissions"in navigator&&navigator.permissions.query&&Promise.all([navigator.permissions.query({name:"notifications"}).catch(()=>null),navigator.permissions.query({name:"geolocation"}).catch(()=>null)]).then(([e,n])=>{e&&(t.permissions={...t.permissions,notifications:e.state}),n&&(t.permissions={...t.permissions,geolocation:n.state})}).catch(()=>{})}catch(e){}return t}function v(e){const t={};if("undefined"==typeof window||"undefined"==typeof document)return t;const n=e||{hasInteraction:!0,focusedElementType:!0,formState:!0,visibility:!0};try{if(n.hasInteraction&&(t.has_interaction=document.hasFocus()||!1),n.focusedElementType){const e=document.activeElement;if(e&&e!==document.body&&(t.focused_element_type=e.tagName.toLowerCase(),"INPUT"===e.tagName)){const n=e.type;t.focused_element_type=`input[type=${n}]`}}if(n.formState){const e=document.forms;if(e&&e.length>0){let n=!1,o=0;Array.from(e).forEach(e=>{const t=e.querySelectorAll("input, textarea, select");o+=t.length,t.forEach(e=>{e.value!==e.defaultValue&&(n=!0)})}),t.form_state={has_forms:!0,has_unsaved_changes:n,active_form_fields:o}}else t.form_state={has_forms:!1,has_unsaved_changes:!1,active_form_fields:0}}n.visibility&&"visibilityState"in document&&(t.visibility={visible:!document.hidden,visibility_state:document.visibilityState},document.hidden&&window.__hiddenSince&&(t.visibility.hidden_duration=Date.now()-window.__hiddenSince),window.__visibilityTracking||(window.__visibilityTracking=!0,document.addEventListener("visibilitychange",()=>{document.hidden?window.__hiddenSince=Date.now():delete window.__hiddenSince})))}catch(e){}return t}function y(e){const t={};if("undefined"==typeof window)return t;const n=e||{pageLoadTime:!0,connectionType:!0,timeOnPage:!0,scrollPosition:!0,pageDimensions:!0,userInteractions:!0};try{if(n.pageLoadTime&&window.performance&&window.performance.timing){const e=window.performance.timing;e.loadEventEnd&&e.navigationStart&&(t.pageLoadTime=e.loadEventEnd-e.navigationStart)}if(n.connectionType&&"connection"in navigator){const e=navigator.connection;e&&e.effectiveType&&(t.connectionType=e.effectiveType)}if(n.scrollPosition){const e=window.pageXOffset||document.documentElement.scrollLeft||0,n=window.pageYOffset||document.documentElement.scrollTop||0;0===e&&0===n||(t.scrollPosition={x:e,y:n})}if(n.timeOnPage&&window.performance&&window.performance.timing&&window.performance.timing.navigationStart&&(t.timeOnPage=Date.now()-window.performance.timing.navigationStart),n.pageDimensions){const e=document.documentElement,n=document.body;if(e&&n){const o=Math.max(n.scrollHeight,e.scrollHeight,n.offsetHeight,e.offsetHeight,n.clientHeight,e.clientHeight),r=Math.max(n.scrollWidth,e.scrollWidth,n.offsetWidth,e.offsetWidth,n.clientWidth,e.clientWidth);t.pageDimensions={scrollHeight:o,scrollWidth:r}}}if(n.userInteractions&&window.performance&&window.performance.eventCounts){const e=window.performance.eventCounts;e.get&&(t.userInteractions={clicks:e.get("click")||0,keyPresses:e.get("keydown")||0,pointerEvents:e.get("pointerdown")||0})}}catch(e){}return t}class b{constructor(e={}){const n=function(){let e,n;try{"undefined"!=typeof process&&process?.env&&(e=process.env.COLLECTLIE_PROJECT_ID,n=process.env.COLLECTLIE_API_KEY,e||(e=process.env.REACT_APP_COLLECTLIE_PROJECT_ID),n||(n=process.env.REACT_APP_COLLECTLIE_API_KEY),e||(e=process.env.NEXT_PUBLIC_COLLECTLIE_PROJECT_ID),n||(n=process.env.NEXT_PUBLIC_COLLECTLIE_API_KEY),e||(e=process.env.VITE_COLLECTLIE_PROJECT_ID),n||(n=process.env.VITE_COLLECTLIE_API_KEY),e||(e=process.env.NUXT_PUBLIC_COLLECTLIE_PROJECT_ID),n||(n=process.env.NUXT_PUBLIC_COLLECTLIE_API_KEY),e||(e=process.env.NUXT_COLLECTLIE_PROJECT_ID),n||(n=process.env.NUXT_COLLECTLIE_API_KEY),e||(e=process.env.PUBLIC_COLLECTLIE_PROJECT_ID),n||(n=process.env.PUBLIC_COLLECTLIE_API_KEY))}catch{}try{const t=globalThis.Deno;t&&t.env&&(e||(e=t.env.get("COLLECTLIE_PROJECT_ID")),n||(n=t.env.get("COLLECTLIE_API_KEY")))}catch{}try{const t=globalThis.Bun;if(t&&t.env){const o=t.env;e||(e=o.COLLECTLIE_PROJECT_ID),n||(n=o.COLLECTLIE_API_KEY)}}catch{}try{"undefined"==typeof document?require("url").pathToFileURL(__filename).href:t&&"SCRIPT"===t.tagName.toUpperCase()&&t.src||new URL("index.js",document.baseURI).href}catch{}return{projectId:e,apiKey:n}}(),o=void 0!==e.isDevelopment?e.isDevelopment:function(){try{if("undefined"!=typeof process&&process?.env&&"development"===process.env.NODE_ENV)return!0}catch{}if("undefined"!=typeof window&&window.location){const e=window.location.hostname;return"localhost"===e||"127.0.0.1"===e||"0.0.0.0"===e||"::1"===e||e.endsWith(".localhost")||e.startsWith("192.168.")||e.startsWith("10.")||e.startsWith("172.")}return!1}();this.config={baseUrl:"https://mmnnfybraewpuvttamvb.supabase.co/functions/v1",validateSchemas:!0,isDevelopment:o,projectId:n.projectId,apiKey:n.apiKey,...e},this.httpClient=new u(this.config)}async submit(e,t){const o=function(e,t=!1){const n=[];t&&(e.projectId||n.push("project_id is required. Set COLLECTLIE_PROJECT_ID environment variable or provide projectId in config."),e.apiKey?"string"==typeof(o=e.apiKey)&&o.length>0||n.push("API key is required."):n.push("API key is required for all environments. Set COLLECTLIE_API_KEY environment variable or provide apiKey in config."));var o;return n}(this.config,!0);if(o.length>0)throw new d("Invalid SDK configuration",o);const r={...e};!r.project_id&&this.config.projectId&&(r.project_id=this.config.projectId),!0===t?(r.browser=m(),r.device=f(),r.source=h(),r.performance=y(),r.errors=g(),r.environment=w(),r.interaction=v()):t&&"object"==typeof t&&(!0===t.browser?r.browser=m():t.browser&&"object"==typeof t.browser&&(r.browser=m(t.browser)),!0===t.device?r.device=f():t.device&&"object"==typeof t.device&&(r.device=f(t.device)),!0===t.source?r.source=h():t.source&&"object"==typeof t.source&&(r.source=h(t.source)),!0===t.performance?r.performance=y():t.performance&&"object"==typeof t.performance&&(r.performance=y(t.performance)),!0===t.errors?r.errors=g():t.errors&&"object"==typeof t.errors&&(r.errors=g(t.errors)),!0===t.environment?r.environment=w():t.environment&&"object"==typeof t.environment&&(r.environment=w(t.environment)),!0===t.interaction?r.interaction=v():t.interaction&&"object"==typeof t.interaction&&(r.interaction=v(t.interaction))),this.config.apiKey&&(r.api_key=this.config.apiKey);const i=p(r,this.config);if(i.length>0)throw new d("Submission data validation failed",i);try{let e;return e=this.httpClient.hasFilesToUpload(r)?await this.httpClient.submitWithFiles(r):await this.httpClient.submitSubmission(r),e}catch(e){throw this.config.isDevelopment&&e instanceof n&&console.error("Collectlie Error:",e.toDetailedString()),e}}}exports.AuthenticationError=r,exports.Collectlie=b,exports.CollectlieError=n,exports.ConfigurationError=d,exports.NetworkError=c,exports.PayloadTooLargeError=i,exports.RateLimitError=s,exports.ServerError=a,exports.ValidationError=o,exports.browserInfo=m,exports.default=b,exports.deviceInfo=f,exports.environmentInfo=w,exports.errorInfo=g,exports.gatherContext=function(e){const t={browser:!0,device:!0,performance:!0,errors:!0,environment:!0,interaction:!0,...e},n={};if(t.browser){const e=m();Object.keys(e).length>0&&(n.browser=e)}if(t.device){const e=f();Object.keys(e).length>0&&(n.device=e)}if(t.performance){const e=y();Object.keys(e).length>0&&(n.performance=e)}if(t.errors){const e=g();Object.keys(e).length>0&&(n.errors=e)}if(t.environment){const e=w();Object.keys(e).length>0&&(n.environment=e)}if(t.interaction){const e=v();Object.keys(e).length>0&&(n.interaction=e)}return n},exports.interactionInfo=v,exports.performanceInfo=y,exports.sourceInfo=h,exports.submit=async function(e,t,n){let o,r;return"boolean"==typeof t||"object"==typeof t&&("browser"in t||"device"in t||"source"in t||"performance"in t||"errors"in t||"environment"in t||"interaction"in t)?r=t:(o=t,r=n),new b(o).submit(e,r)},exports.validateSubmissionData=p;