(()=>{"use strict";class Preconditions{static checkArgument(cond,msg,...args){if(!cond)throw new Error(msg==null?"invalid argument":Preconditions.format(msg,...args))}static checkState(cond,msg,...args){if(!cond)throw new Error(msg==null?"invalid state":Preconditions.format(msg,...args))}static checkEquals(a,b,msg,...args){if(a!==b)throw new Error(msg==null?Preconditions.format("{} != {}",Preconditions.stringify(a),Preconditions.stringify(b)):Preconditions.format(msg,...args))}static stringify(x){if(x==null||typeof x==="symbol")return String(x);else try{return JSON.stringify(x)}catch(e){return String(x)}}static checkExists(x,msg,...args){if(x==null)throw new Error(msg==null?"argument is null":Preconditions.format(msg,...args));return x}static format(template,...args){let i=0;return template.replace(/\{}/g,(()=>i{const maybeFullstop=opts.message.endsWith(".")?"":".";return`[${opts.code}]: ${opts.message}${maybeFullstop}`.trim()};class CanvaErrorClass extends Error{constructor(opts){opts.code=appSandboxErrorCodeMapper(opts.code);super(formattedErrorMessage(opts));this.code=opts.code;this.name="CanvaError";this.rawMessage=opts.message;Object.setPrototypeOf(this,CanvaErrorClass.prototype)}}function setAppSandboxErrorCodeMapper(mapper){appSandboxErrorCodeMapper=mapper}let appSandboxErrorCodeMapper=code=>code;class MessageBus{constructor(handler,port,errorService){this.handler=handler;this.port=port;this.errorService=errorService;this.send=message=>{try{this.port.postMessage(message);return Result.Ok()}catch(e){this.errorService.errorException(e);return Result.Err(e)}};this.onMessageError=e=>{this.errorService.errorException(e)};this.onMessage=({data})=>{if(!data){this.errorService.error(new CanvaErrorClass({code:"internal_error",message:`missing data in 'MessageEvent'`}));return}try{this.handler.receive(data)}catch(e){this.errorService.errorException(e)}};this.port.onmessage=this.onMessage;this.port.onmessageerror=this.onMessageError}}function uuidv4(rng){const randomValues=getRandomValues(rng,31);let currentRandomValue=0;return`${1e7}-${1e3}-${4e3}-${8e3}-${1e11}`.replace(/[018]/g,(function(c){const cN=Number(c);return(cN^randomValues[currentRandomValue++]&15>>cN/4).toString(16)}))}const HEX_CHARS="0123456789abcdef";function uuidv7(){const bytes=Uint8Array.from(getRandomValues(undefined,16));const now=Date.now();bytes[0]=Math.trunc(now/1099511627776)&255;bytes[1]=Math.trunc(now/4294967296)&255;bytes[2]=Math.trunc(now/16777216)&255;bytes[3]=Math.trunc(now/65536)&255;bytes[4]=Math.trunc(now/256)&255;bytes[5]=now&255;bytes[6]=112|bytes[6]&15;bytes[8]=128|bytes[8]&63;let hex="";for(let i=0;i<16;i++)hex+=HEX_CHARS[bytes[i]>>>4]+HEX_CHARS[bytes[i]&15];return`${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`}function getRandomValues(rng,amount){if(!rng&&typeof window!=="undefined"&&typeof window.crypto!=="undefined"&&typeof window.crypto.getRandomValues==="function")return window.crypto.getRandomValues(new Uint8Array(amount));const random=rng??Math.random;return Array.from({length:amount},(()=>Math.floor(random()*255)))}const ACK_INTERVAL=9e3;const INITIAL_ACK_TIMEOUT=2e4;const SUBSEQUENT_ACK_TIMEOUT=3e4;class PromiseTimeoutError extends Error{constructor(){super("[internal_error] Comms promise timed out.")}}const REJECT_ON_NEXT_TICK_DELAY_MS=500;class PromiseWithTimeout{reset(newTimeoutMs){if(newTimeoutMs)this.timeoutMs=newTimeoutMs;this.setTimeout()}resolve(value){clearTimeout(this.timeoutId);this.resolveFn(value)}reject(reason){clearTimeout(this.timeoutId);this.rejectFn(reason)}promise(){return this.p}rejectOnNextTick(){this.timeoutId=setTimeout((()=>{this.rejectFn(new PromiseTimeoutError)}),REJECT_ON_NEXT_TICK_DELAY_MS)}setTimeout(){clearTimeout(this.timeoutId);this.timeoutId=setTimeout((()=>{this.rejectOnNextTick()}),Math.max(this.timeoutMs-REJECT_ON_NEXT_TICK_DELAY_MS,REJECT_ON_NEXT_TICK_DELAY_MS))}constructor(timeoutMs){this.timeoutMs=timeoutMs;this.p=new Promise(((resolve,reject)=>{this.resolveFn=resolve;this.rejectFn=reject}));this.setTimeout()}}const RECENT_TIMED_OUT_REQUEST_LIMIT=32;class Client{request(path,payload){const pendingRequests=this.pendingRequests;const recentTimedOutRequests=this.recentTimedOutRequests;const requestPromise=new PromiseWithTimeout(INITIAL_ACK_TIMEOUT);const requestId=this.requestIdGenerator();const resultPromise=awaitResult();const result=this.send(requestId,path,payload);if(!result.ok){this.errorService.errorException(result.error,{errorMessagePrefix:"unable to send request",tags:new Map([["type","request"],["path",path]])});requestPromise.reject(result.error)}return resultPromise;async function awaitResult(){pendingRequests.set(requestId,{path,requestPromise});try{const response=await requestPromise.promise();return Result.Ok(response)}catch(e){if(e instanceof PromiseTimeoutError){recentTimedOutRequests.set(requestId,[path,Date.now()]);if(recentTimedOutRequests.size>RECENT_TIMED_OUT_REQUEST_LIMIT)recentTimedOutRequests.delete(recentTimedOutRequests.keys().next().value);return Result.Err(new CanvaErrorClass({code:"internal_error",message:`Comms promise timed out (${path}).`}))}return Result.Err(e)}finally{pendingRequests.delete(requestId)}}}handleReply(msg){const{requestId,type}=msg;const{path,requestPromise:request}=this.pendingRequests.get(requestId)||{};if(!request){if(type!=="ack"){const[path,timestamp]=this.recentTimedOutRequests.get(requestId)??["not_recently_timed_out",undefined];const extra=timestamp!==undefined?new Map([["time_since_timeout",Date.now()-timestamp]]):undefined;this.errorService.error(`request has already been handled and resolved or was not sent from this client`,{tags:new Map([["type",type],["path",path]]),extra})}return}switch(type){case"response":request.resolve(msg.payload);return;case"ack":request.reset(SUBSEQUENT_ACK_TIMEOUT);return;case"error":this.errorService.addBreadCrumb({level:"info",category:"sandbox_comms",message:"Error response received",data:{["path"]:path??"unknown"}});const{code,message}=msg;request.reject(new CanvaErrorClass({code,message}));return;default:throw new UnreachableError(msg)}}constructor(send,errorService,requestIdGenerator=uuidv4){this.send=send;this.errorService=errorService;this.requestIdGenerator=requestIdGenerator;this.pendingRequests=new Map;this.recentTimedOutRequests=new Map}}const RequestHandlerErrorCodes={internalError:()=>"Something went wrong on our end, if this issue persists please contact us.",noHandlerForPath:path=>`No request handler configured for path: "${path}".`,handlerForPathAlreadyDefined:path=>`Handler for '${path}' is already defined.`};class RequestHandler{addErrorObserver(observer){this.errorObservers.add(observer);return()=>this.errorObservers.delete(observer)}handle(path,handler){if(this.requestHandler.has(path))throw new CanvaErrorClass({code:"internal_error",message:RequestHandlerErrorCodes.handlerForPathAlreadyDefined(path)});this.requestHandler.set(path,handler);return()=>this.requestHandler.delete(path)}async handleRequest(body){const{requestId,path,payload}=body;const handler=this.requestHandler.get(path);if(!handler){const result=this.messenger.sendError(requestId,"internal_error",RequestHandlerErrorCodes.noHandlerForPath(path));if(!result.ok)this.errorService.criticalException(result.error,{errorMessagePrefix:"unable to send error response",tags:new Map([["type","request"],["path",path]])});return}this.messenger.sendAck(requestId);const intervalId=setInterval((()=>this.messenger.sendAck(requestId)),ACK_INTERVAL);let observableError;try{const resPayload=await handler(payload);clearInterval(intervalId);this.messenger.sendResponse(requestId,resPayload)}catch(e){clearInterval(intervalId);let errorCode="internal_error";let errorMessage=RequestHandlerErrorCodes.internalError();if(e instanceof CanvaErrorClass){observableError=e;if(e.code==="internal_error")this.errorService.errorException(e,{errorMessagePrefix:"Internal error in comms handler",tags:new Map([["type","request"],["path",path]])});else{errorCode=e.code;errorMessage=e.rawMessage}}else if(this.reportNonCanvaErrors)this.errorService.errorException(e,{errorMessagePrefix:"Unexpected error type thrown from comms handler",tags:new Map([["type","request"],["path",path]])});else this.devConsole.error(e);const result=this.messenger.sendError(requestId,errorCode,errorMessage);if(!result.ok)this.errorService.criticalException(result.error,{errorMessagePrefix:"unable to send error response",tags:new Map([["type","request"],["path",path]])})}if(observableError==null)return;for(const cb of this.errorObservers)try{cb(observableError)}catch(e){this.errorService.warningException(e,{errorMessagePrefix:"Error executing errorObserver"})}}constructor(messenger,errorService,reportNonCanvaErrors,devConsole=console){this.messenger=messenger;this.errorService=errorService;this.reportNonCanvaErrors=reportNonCanvaErrors;this.devConsole=devConsole;this.requestHandler=new Map;this.errorObservers=new Set}}class SandboxCommsBase{constructor(port,errorService,reportNonCanvaErrors){this.request=(path,payload)=>this.client.request(path,payload);this.handle=(path,handler)=>this.requestHandler.handle(path,handler);this.addErrorObserver=observer=>this.requestHandler.addErrorObserver(observer);const handleMessage=message=>{switch(message.type){case"ack":case"error":case"response":this.client.handleReply(message);return;case"request":this.requestHandler.handleRequest(message);return;default:throw new UnreachableError(message)}};const messenger=new MangleSafeMessageBus(handleMessage,port,errorService.createChild("bus"));this.client=new Client(messenger.sendRequest,errorService.createChild("client"));this.requestHandler=new RequestHandler(messenger,errorService.createChild("requestHandler"),reportNonCanvaErrors)}}class MangleSafeMessageBus{sendResponse(requestId,payload){return this.bus.send({["type"]:"response",["requestId"]:requestId,["payload"]:payload})}sendError(requestId,code,message){return this.bus.send({["type"]:"error",["requestId"]:requestId,["code"]:code,["message"]:message})}sendAck(requestId){return this.bus.send({["type"]:"ack",["requestId"]:requestId})}constructor(handleMessage,port,errorService){this.handleMessage=handleMessage;this.sendRequest=(requestId,path,payload)=>this.bus.send({["type"]:"request",["requestId"]:requestId,["path"]:path,["payload"]:payload});this.onReceive=message=>{switch(message["type"]){case"ack":this.handleMessage({type:"ack",requestId:message["requestId"]});return;case"error":this.handleMessage({type:"error",requestId:message["requestId"],code:message["code"],message:message["message"]});return;case"response":this.handleMessage({type:"response",requestId:message["requestId"],payload:message["payload"]});return;case"request":this.handleMessage({type:"request",requestId:message["requestId"],path:message["path"],payload:message["payload"]});return;default:throw new UnreachableError(message)}};this.bus=new MessageBus({receive:this.onReceive},port,errorService)}}const VerifyError={MISSING_DATA:"missing 'data' field in MessageEvent",MISSING_SOURCE:"'sandboxCommsSource' is missing in MessageEvent data object",INVALID_SOURCE:"invalid source",UNKNOWN_CLIENT_ID:"unknown client id"};function createInitialiseMessage(sandboxCommsSource,clientId){return{["sandboxCommsSource"]:sandboxCommsSource,["clientId"]:clientId}}function verifyMessage(data,expectedSource,expectedClientId){if(!data)return Result.Err("missing 'data' field in MessageEvent");const msg=data;const source=msg["sandboxCommsSource"];if(!source)return Result.Err("'sandboxCommsSource' is missing in MessageEvent data object");if(source!==expectedSource)return Result.Err("invalid source");if(msg["clientId"]!==expectedClientId)return Result.Err("unknown client id");return Result.Ok()}async function connectToParent(errorService,parentOrigin,{parent,addEventListener,removeEventListener}=window,clientId){const portPromise=Promise.withResolvers();const messageHandler=({ports,data})=>{const msg=verifyMessage(data,"parent",clientId);if(!msg.ok){switch(msg.error){case VerifyError.INVALID_SOURCE:errorService.info(msg.error,{errorMessagePrefix:"failed to verify message",extra:new Map([["data.sandboxCommsSource",data?.sandboxCommsSource]])});break;case VerifyError.MISSING_DATA:case VerifyError.MISSING_SOURCE:case VerifyError.UNKNOWN_CLIENT_ID:break;default:throw new UnreachableError(msg.error)}return}if(ports.length!==1){errorService.error("invalid number of ports received from the parent");return}const[port]=ports;portPromise.resolve(port)};addEventListener("message",messageHandler);try{const initMessage=createInitialiseMessage("iframe",clientId);parent.postMessage(initMessage,parentOrigin);const port=await portPromise.promise;return Result.Ok(new SandboxCommsBase(port,errorService.createChild("comms"),false))}catch(e){return Result.Err(e)}finally{removeEventListener("message",messageHandler)}}function deserializeRequest(message_path,proto,request){if(request===undefined)throw new CanvaErrorClass({code:"internal_error",message:`${message_path}: request cannot be undefined.`});return proto.deserialize(request)}function handleMessageFromHost(comms,message_path,messageArgProto,messageHandler,responseProto){return comms.handle(message_path,(async messageObject=>{const message=deserializeRequest(message_path,messageArgProto,messageObject);const response=await messageHandler(message);if(responseProto)return responseProto.serialize(response)}))}async function runRequest(comms,messagePath,requestProto,request,responseProto){const response=await comms.request(messagePath,requestProto.serialize(request));if(!response.ok){if(response.error instanceof CanvaErrorClass)throw response.error;throw new CanvaErrorClass({code:"internal_error",message:`Something went wrong during request ${messagePath}`})}if(responseProto){if(response.value===undefined)throw new CanvaErrorClass({code:"internal_error",message:`Expected a response from ${messagePath}, but got nothing`});return responseProto.deserialize(response.value)}}const MessagePaths={INIT_DATA:"INIT_DATA",DATA_RENDER_READY:"DATA_RENDER_READY"};function isPromiseLike(p){return p!=null&&p.then!=null}function memoize(fn,{invalidateOnError}={invalidateOnError:false}){let promiseDidReject=false;let result;const memoFn=(...args)=>{Preconditions.checkArgument(args.length===0);if(result==null||invalidateOnError&&(!result.ok||promiseDidReject))try{promiseDidReject=false;result=Result.Ok(fn());if(isPromiseLike(result.value))result.value.then(null,(_e=>promiseDidReject=true))}catch(e){result=Result.Err(e)}if(result.ok)return result.value;else throw result.error};return memoFn}function memoize1(fn){const cache=new WeakMap;const memoFn=(key,...rest)=>{Preconditions.checkArgument(rest.length===0);if(!cache.has(key))cache.set(key,fn(key));return cache.get(key)};return memoFn}const MessageKind={CONCRETE:1,ONEOF:2};const FieldLabel={CONSTANT:1,REQUIRED:2,OPTIONAL:3,REPEATED:4,MAP:5};const FieldKind={PRIMITIVE:1,MESSAGE:2,ENUM:3};const makeType=t=>t;const ProtoType={STRING:makeType({typeOfValue:"string"}),BOOLEAN:makeType({typeOfValue:"boolean",defaultValue:false,fixedSize:1}),DOUBLE:makeType({typeOfValue:"number",defaultValue:0,fixedSize:8}),INT32:makeType({typeOfValue:"number",defaultValue:0}),INT64:makeType({typeOfValue:"number",defaultValue:0}),BYTES:makeType({typeOfValue:"Uint8Array"})};function makeFieldConfig(tag,fieldLabel,typeOfValue,jsonFullKey,jsonFullValue,value,defaults,defaultField,defaultValue,obj,typeOfKey){return{tag,fieldLabel,typeOfValue,jsonFullKey,jsonFullValue,value,defaults,default:defaultField,defaultValue,obj,typeOfKey}}function constantField(params){const{tag,jsonFullKeyOrJsonMiniKey,jsonFullValue,value,defaults}=params;const jsonFullKey=jsonFullKeyOrJsonMiniKey===DISCRIMINATOR_JSON_MINI_KEY?undefined:jsonFullKeyOrJsonMiniKey;return makeFieldConfig(tag,FieldLabel.CONSTANT,"string",jsonFullKey,jsonFullValue,value,defaults,undefined,undefined,undefined,undefined)}function requiredField(valueType,jsonFullKey,tag,def){return makeFieldConfig(tag,FieldLabel.REQUIRED,valueType.typeOfValue,jsonFullKey,undefined,undefined,undefined,def!=null?def:valueType.defaultValue,valueType.defaultValue,undefined,undefined)}function optionalField(valueType,jsonFullKey,tag){return makeFieldConfig(tag,FieldLabel.OPTIONAL,valueType.typeOfValue,jsonFullKey,undefined,undefined,undefined,undefined,valueType.defaultValue,undefined,undefined)}function repeatedField(valueType,jsonFullKey,tag){return makeFieldConfig(tag,FieldLabel.REPEATED,valueType.typeOfValue,jsonFullKey,undefined,undefined,undefined,undefined,undefined,undefined,undefined)}function mapField(keyType,valueType){return(tagOrJsonFullKey,tagOrObj,maybeObj)=>{const{tag,jsonFullKey,other1:obj}=getOptions(tagOrJsonFullKey,tagOrObj,maybeObj);let typeOfValue;if(valueType==="object")typeOfValue="object";else if(valueType==="enum")typeOfValue="string";else typeOfValue=valueType.typeOfValue;return makeFieldConfig(tag,FieldLabel.MAP,typeOfValue,jsonFullKey,undefined,undefined,undefined,undefined,undefined,obj,keyType.typeOfValue)}}class Proto{static constantString(jsonFullKeyOrJsonMiniKey,jsonFullValueOrTag,tagOrValue,maybeValue){const{tag,jsonFullKey:jsonFullValue,other1:value}=getOptions(jsonFullValueOrTag,tagOrValue,maybeValue);return constantField({tag,jsonFullKeyOrJsonMiniKey,jsonFullValue,value,defaults:false})}static constantStringWithDefault(jsonFullKeyOrJsonMiniKey,jsonFullValueOrTag,tagOrValue,maybeValue){const{tag,jsonFullKey:jsonFullValue,other1:value}=getOptions(jsonFullValueOrTag,tagOrValue,maybeValue);return constantField({tag,jsonFullKeyOrJsonMiniKey,jsonFullValue,value,defaults:true})}static requiredObject(tagOrJsonFullKey,tagOrObj,maybeObj){const{tag,jsonFullKey,other1:obj}=getOptions(tagOrJsonFullKey,tagOrObj,maybeObj);return makeFieldConfig(tag,FieldLabel.REQUIRED,"object",jsonFullKey,undefined,undefined,undefined,undefined,undefined,obj,undefined)}static optionalObject(tagOrJsonFullKey,tagOrObj,maybeObj){const{tag,jsonFullKey,other1:obj}=getOptions(tagOrJsonFullKey,tagOrObj,maybeObj);return makeFieldConfig(tag,FieldLabel.OPTIONAL,"object",jsonFullKey,undefined,undefined,undefined,undefined,undefined,obj,undefined)}static repeatedObject(tagOrJsonFullKey,tagOrObj,maybeObj){const{tag,jsonFullKey,other1:obj}=getOptions(tagOrJsonFullKey,tagOrObj,maybeObj);return makeFieldConfig(tag,FieldLabel.REPEATED,"object",jsonFullKey,undefined,undefined,undefined,undefined,undefined,obj,undefined)}static requiredStringEnum(tagOrJsonFullKey,tagOrObj,objOrDef,maybeDef){const{tag,jsonFullKey,other1:obj,other2:def}=getOptions(tagOrJsonFullKey,tagOrObj,objOrDef,maybeDef);return makeFieldConfig(tag,FieldLabel.REQUIRED,"string",jsonFullKey,undefined,undefined,undefined,def,undefined,obj,undefined)}static optionalStringEnum(tagOrJsonFullKey,tagOrObj,maybeObj){const{tag,jsonFullKey,other1:obj}=getOptions(tagOrJsonFullKey,tagOrObj,maybeObj);return makeFieldConfig(tag,FieldLabel.OPTIONAL,"string",jsonFullKey,undefined,undefined,undefined,undefined,undefined,obj,undefined)}static repeatedStringEnum(tagOrJsonFullKey,tagOrObj,maybeObj){const{tag,jsonFullKey,other1:obj}=getOptions(tagOrJsonFullKey,tagOrObj,maybeObj);return makeFieldConfig(tag,FieldLabel.REPEATED,"string",jsonFullKey,undefined,undefined,undefined,undefined,undefined,obj,undefined)}static createMessage(schema,options={}){const init=memoize((()=>{const fields=schema();const fieldNames=Object.keys(fields);const fieldsByTag={};const constantsByTag={};for(let i=0;i{throw new TypeError(`Unproducible oneof case ${pathTrace(path)}`)}:(message,path)=>{if(message==null||typeof message!=="object")throw new TypeError(`Expected type object, found: ${moreSpecificTypeof(message)} ${pathTrace(path)}`);const{fieldMetadata}=init();const res={};for(let i=0;i{const config=schema();const discriminatorKey=Object.keys(config)[0];let discriminatorTag;let discriminatorJsonKeyEncodings;const nameToObject=new Map;const serializedToObject=new Map;const tagToObject=new Map;for(let i=0;i{const{discriminatorKey,nameToObject}=init();const type=t[discriminatorKey];const obj=nameToObject.get(type);if(!obj)throw new TypeError(`Unknown oneof deserialized case: ${JSON.stringify(type)} ${pathTrace(path)}`);return obj.serializeWithPath(t,path)};const deserializeWithPath=(o,path)=>{const{serializedToObject,discriminatorJsonKeyEncodings,defaultObject}=init();const{primaryJsonKey,secondaryJsonKey}=discriminatorJsonKeyEncodings;let type=o[primaryJsonKey];if(type==null&&secondaryJsonKey)type=o[secondaryJsonKey];if(type==null&&defaultObject)return defaultObject.deserializeWithPath(o,path);const obj=serializedToObject.get(type);if(!obj)throw new TypeError(`Unknown oneof serialized case: ${JSON.stringify(type)} ${pathTrace(path)}`);return obj.deserializeWithPath(o,path)};return{init,serialize:t=>serializeWithPath(t,[]),serializeWithPath,deserialize:o=>deserializeWithPath(o,[]),deserializeWithPath}}static createEnumUtil(schema,baseNumber=0,options={}){const init=memoize((()=>{const config=schema();const values=[];const serializedToValue=new Map;const valueToSerialized=new Map;const valueToProtobufSerialized=new Map;const protobufSerializedToValue=new Map;const unproducible=new Set;let i=0;let index=1;while(i{const{unproducible}=init();if(unproducible&&unproducible.has(value))throw new TypeError(`Unproducible enum value: ${JSON.stringify(value)} ${path?pathTrace(path):""}`);const serialized=map.get(value);if(serialized==null)throw new TypeError(`The proto enum serializer failed to serialize value ${JSON.stringify(value)} into JSON.\nIt does not recognize value ${JSON.stringify(value)} as a valid member of the TypeScript enum.\n${path?pathTrace(path):""}`);return serialized};const deserializeWithPath=(jsonValue,path)=>{const value=init().serializedToValue.get(jsonValue);if(value==null)throw new TypeError(`The proto enum deserializer failed to deserialize JSON ${JSON.stringify(jsonValue)} into an enum value.\nIt does not recognize JSON ${JSON.stringify(jsonValue)} as a valid JSON value encoding of the enum.\n${pathTrace(path)}`);return value};return{values:()=>init().values,producibleValues:()=>{const{values,unproducible}=init();if(unproducible==null)return values;return values.filter((value=>!unproducible.has(value)))},serialize:value=>getSerialized(value,init().valueToSerialized,[]),serializeWithPath:(value,path)=>getSerialized(value,init().valueToSerialized,path),deserialize:jsonValue=>deserializeWithPath(jsonValue,[]),deserializeWithPath}}}Proto.requiredDouble=(a,b,c)=>{const{tag,jsonFullKey,other1}=getOptions(a,b,c);return requiredField(ProtoType.DOUBLE,jsonFullKey,tag,other1)};Proto.requiredInt32=(a,b,c)=>{const{tag,jsonFullKey,other1}=getOptions(a,b,c);return requiredField(ProtoType.INT32,jsonFullKey,tag,other1)};Proto.requiredInt64=(a,b,c)=>{const{tag,jsonFullKey,other1}=getOptions(a,b,c);return requiredField(ProtoType.INT64,jsonFullKey,tag,other1)};Proto.optionalDouble=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return optionalField(ProtoType.DOUBLE,jsonFullKey,tag)};Proto.optionalInt32=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return optionalField(ProtoType.INT32,jsonFullKey,tag)};Proto.optionalInt64=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return optionalField(ProtoType.INT64,jsonFullKey,tag)};Proto.repeatedDouble=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return repeatedField(ProtoType.DOUBLE,jsonFullKey,tag)};Proto.repeatedInt32=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return repeatedField(ProtoType.INT32,jsonFullKey,tag)};Proto.repeatedInt64=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return repeatedField(ProtoType.INT64,jsonFullKey,tag)};Proto.requiredString=(a,b,c)=>{const{tag,jsonFullKey,other1}=getOptions(a,b,c);return requiredField(ProtoType.STRING,jsonFullKey,tag,other1)};Proto.optionalString=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return optionalField(ProtoType.STRING,jsonFullKey,tag)};Proto.repeatedString=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return repeatedField(ProtoType.STRING,jsonFullKey,tag)};Proto.requiredBoolean=(a,b,c)=>{const{tag,jsonFullKey,other1}=getOptions(a,b,c);return requiredField(ProtoType.BOOLEAN,jsonFullKey,tag,other1)};Proto.optionalBoolean=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return optionalField(ProtoType.BOOLEAN,jsonFullKey,tag)};Proto.repeatedBoolean=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return repeatedField(ProtoType.BOOLEAN,jsonFullKey,tag)};Proto.requiredBytes=(a,b,c)=>{const{tag,jsonFullKey,other1}=getOptions(a,b,c);return requiredField(ProtoType.BYTES,jsonFullKey,tag,other1)};Proto.optionalBytes=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return optionalField(ProtoType.BYTES,jsonFullKey,tag)};Proto.repeatedBytes=(a,b)=>{const{tag,jsonFullKey}=getOptions(a,b);return repeatedField(ProtoType.BYTES,jsonFullKey,tag)};Proto.booleanInt64Map=mapField(ProtoType.BOOLEAN,ProtoType.INT64);Proto.int32Int32Map=mapField(ProtoType.INT32,ProtoType.INT32);Proto.int32Int64Map=mapField(ProtoType.INT32,ProtoType.INT64);Proto.int32BoolMap=mapField(ProtoType.INT32,ProtoType.BOOLEAN);Proto.int32DoubleMap=mapField(ProtoType.INT32,ProtoType.DOUBLE);Proto.int32StringMap=mapField(ProtoType.INT32,ProtoType.STRING);Proto.int32StringEnumMap=mapField(ProtoType.INT32,"enum");Proto.int32ObjectMap=mapField(ProtoType.INT32,"object");Proto.int32BytesMap=mapField(ProtoType.INT32,ProtoType.BYTES);Proto.int64Int32Map=mapField(ProtoType.INT64,ProtoType.INT32);Proto.int64Int64Map=mapField(ProtoType.INT64,ProtoType.INT64);Proto.int64BooleanMap=mapField(ProtoType.INT64,ProtoType.BOOLEAN);Proto.int64DoubleMap=mapField(ProtoType.INT64,ProtoType.DOUBLE);Proto.int64StringMap=mapField(ProtoType.INT64,ProtoType.STRING);Proto.int64StringEnumMap=mapField(ProtoType.INT64,"enum");Proto.int64ObjectMap=mapField(ProtoType.INT64,"object");Proto.int64BytesMap=mapField(ProtoType.INT64,ProtoType.BYTES);Proto.doubleInt32Map=mapField(ProtoType.DOUBLE,ProtoType.INT32);Proto.doubleInt64Map=mapField(ProtoType.DOUBLE,ProtoType.INT64);Proto.doubleBoolMap=mapField(ProtoType.DOUBLE,ProtoType.BOOLEAN);Proto.doubleDoubleMap=mapField(ProtoType.DOUBLE,ProtoType.DOUBLE);Proto.doubleStringMap=mapField(ProtoType.DOUBLE,ProtoType.STRING);Proto.doubleStringEnumMap=mapField(ProtoType.DOUBLE,"enum");Proto.doubleObjectMap=mapField(ProtoType.DOUBLE,"object");Proto.doubleBytesMap=mapField(ProtoType.DOUBLE,ProtoType.BYTES);Proto.stringInt32Map=mapField(ProtoType.STRING,ProtoType.INT32);Proto.stringInt64Map=mapField(ProtoType.STRING,ProtoType.INT64);Proto.stringBooleanMap=mapField(ProtoType.STRING,ProtoType.BOOLEAN);Proto.stringDoubleMap=mapField(ProtoType.STRING,ProtoType.DOUBLE);Proto.stringStringMap=mapField(ProtoType.STRING,ProtoType.STRING);Proto.stringStringEnumMap=mapField(ProtoType.STRING,"enum");Proto.stringObjectMap=mapField(ProtoType.STRING,"object");Proto.stringBytesMap=mapField(ProtoType.STRING,ProtoType.BYTES);function deriveFieldMetadata(fields,dualDeserializationConfig){return Object.entries(fields).map((([name,config])=>{const fieldEncodings=deriveFieldEncodings(config,dualDeserializationConfig);return{config,name,primaryJsonKey:fieldEncodings.keyEncodings.primaryJsonKey,secondaryJsonKey:fieldEncodings.keyEncodings.secondaryJsonKey,primaryJsonValue:fieldEncodings.valueEncodings?.primaryJsonValue,secondaryJsonValue:fieldEncodings.valueEncodings?.secondaryJsonValue}}))}function deriveFieldEncodings(fieldConfig,dualDeserializationConfig){let valueEncodings;let jsonMiniKey=toJsonMini(fieldConfig.tag-1);if(fieldConfig.fieldLabel===FieldLabel.CONSTANT){const{primary:primaryJsonValue,secondary:secondaryJsonValue}=choosePrimaryAndSecondaryJSONFromConfig(jsonMiniKey,fieldConfig.jsonFullValue,dualDeserializationConfig);jsonMiniKey=DISCRIMINATOR_JSON_MINI_KEY;valueEncodings={primaryJsonValue,secondaryJsonValue}}const{primary:primaryJsonKey,secondary:secondaryJsonKey}=choosePrimaryAndSecondaryJSONFromConfig(jsonMiniKey,fieldConfig.jsonFullKey,dualDeserializationConfig);const keyEncodings={primaryJsonKey,secondaryJsonKey};return{keyEncodings,valueEncodings}}function choosePrimaryAndSecondaryJSONFromConfig(jsonMini,jsonFull,dualDeserializationConfig){if(!jsonFull){if(dualDeserializationConfig!==undefined)throw new Error("Dual Deserialization config templated but JSON full key/value wasn't");return{primary:jsonMini,secondary:undefined}}if(dualDeserializationConfig===undefined)return{primary:jsonFull,secondary:undefined};else if(dualDeserializationConfig===0)return{primary:jsonMini,secondary:jsonFull};else if(dualDeserializationConfig===1)return{primary:jsonFull,secondary:jsonMini};throw new Error("function should have been exhaustive, but wasn't")}function makeRepeatedTypeError(keyEncodings,value,expectedType,path){return new TypeError(`Expected repeated ${expectedType} value for key ${expectedKeys(keyEncodings)}, found: ${moreSpecificTypeof(value)} ${pathTrace(path)}`)}function makeOptionalTypeError(keyEncodings,value,expectedType,path){return new TypeError(`Expected optional ${expectedType} value for key ${expectedKeys(keyEncodings)}, found: ${moreSpecificTypeof(value)} ${pathTrace(path)}`)}function makeRequiredTypeError(keyEncodings,value,expectedType,path,index){const atIndex=index!==undefined?` at index ${index}`:"";return new TypeError(`Expected ${expectedType} value${atIndex} for key ${expectedKeys(keyEncodings)}, found: ${moreSpecificTypeof(value)} ${pathTrace(path)}`)}function expectedKeys(keyEncodings){const{primaryJsonKey,secondaryJsonKey}=keyEncodings;if(secondaryJsonKey)return`either "${primaryJsonKey}" OR "${secondaryJsonKey}"`;return`"${primaryJsonKey}"`}function expectedValues(valueEncodings){const{primaryJsonValue,secondaryJsonValue}=valueEncodings;if(secondaryJsonValue)return`either "${primaryJsonValue}" OR "${secondaryJsonValue}"`;return`"${primaryJsonValue}"`}function pathTrace(path){return`(path: .${path.join(".")})`}function moreSpecificTypeof(value){if(value===null)return"null";if(Array.isArray(value))return"array";return typeof value}const DualDeserializationConfig={MINI_PRIMARY_FULL_SECONDARY:0,FULL_PRIMARY_MINI_SECONDARY:1};const DISCRIMINATOR_JSON_MINI_KEY="A?";const JSON_MINI_ALPHABET="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";function toJsonMini(x){if(x0){builder.push(JSON_MINI_ALPHABET.charAt(x%JSON_MINI_ALPHABET.length));x=Math.floor(x/JSON_MINI_ALPHABET.length)}return builder.reverse().join("")}}function getOptions(tagOrJsonFullKey,tagOrOther1,other1OrOther2,maybeOther2){if(typeof tagOrJsonFullKey==="string")return{jsonFullKey:tagOrJsonFullKey,tag:tagOrOther1,other1:other1OrOther2,other2:maybeOther2};else return{tag:tagOrJsonFullKey,other1:tagOrOther1,other2:other1OrOther2}}function isCorrectWireType(value,typeOfValue){return typeof value===typeOfValue||isCorrectBytesWireType(value,typeOfValue)}function isCorrectBytesWireType(value,typeOfValue){return typeOfValue==="Uint8Array"&&typeof value==="string"}function toBase64(bytes){const binString=Array.from(bytes,(byte=>String.fromCodePoint(byte))).join("");return btoa(binString)}function fromBase64(base64){return Uint8Array.from(atob(base64),(m=>m.codePointAt(0)))}const InitDataRequest=Proto.createMessage((()=>({})));const WebsiteContext=Proto.createMessage((()=>({deploymentId:Proto.requiredString(1),accessToken:Proto.requiredString(2)})));const InitDataResponse=Proto.createMessage((()=>({documentId:Proto.optionalString("documentId",1),elementId:Proto.optionalString("elementId",2),pageId:Proto.optionalString("pageId",6),websiteContext:Proto.optionalObject("websiteContext",3,WebsiteContext),documentExtension:Proto.optionalString("documentExtension",5),isPreview:Proto.optionalBoolean("isPreview",4)})),{dualDeserializationConfig:DualDeserializationConfig.MINI_PRIMARY_FULL_SECONDARY});const RenderReadyRequest=Proto.createMessage((()=>({})));const RenderReadyResponse=Proto.createMessage((()=>({})));const DATA_CLIENT_ID="canva-code-data-sdk";function setupDataRequestHandlers(comms,handler){handleMessageFromHost(comms,MessagePaths.INIT_DATA,InitDataRequest,(request=>handler.handleInitData(request)),InitDataResponse);handleMessageFromHost(comms,MessagePaths.DATA_RENDER_READY,RenderReadyRequest,(request=>handler.handleRenderReady(request)),RenderReadyResponse)}class DataClientComms{async sendInitData(request){const result=await this.comms.request(MessagePaths.INIT_DATA,InitDataRequest.serialize(request));const value=extractValue(result,MessagePaths.INIT_DATA);return InitDataResponse.deserialize(value)}async sendRenderReady(request){const result=await this.comms.request(MessagePaths.DATA_RENDER_READY,RenderReadyRequest.serialize(request));const value=extractValue(result,MessagePaths.DATA_RENDER_READY);return RenderReadyResponse.deserialize(value)}constructor(comms){this.comms=comms}}function extractValue(result,messagePath){if(!result.ok)throw new Error(`Encountered an error while sending ${messagePath} request: ${result.error}`);if(result.value==null)throw new Error(`${messagePath}: Result cannot be empty`);return result.value}const SYSTEM_LOG_MARKER=Symbol("canvaSystemLog");class ConsoleErrorService{log(method,...args){console[method](SYSTEM_LOG_MARKER,`[CLIENT (${this.context})]`,...args)}report(method,severity,...args){const[error,extra]=args;this.beforeReportHandlers.forEach((handler=>handler(severity,error,extra)));this.log(method,...args)}createChild(name){const child=new ConsoleErrorService(`${this.context}:${name}`);child.beforeReportHandlers=this.beforeReportHandlers;return child}withOfflineStatus(){}setContext(context){this.log("debug","context set",context)}setTag(key,value){this.log("debug","tag set",key,value)}addBeforeSendHandler(){}addBeforeReportHandler(handler){this.beforeReportHandlers.push(handler)}setFilters(){}setSensitiveStrings(sensitiveStrings){}addBreadCrumb(breadCrumb){this.log("debug","breadcrumb added",breadCrumb)}debug(error,extra){this.report("debug","debug",error,extra)}info(...args){this.report("info","info",...args)}warn(...args){this.report("warn","warning",...args)}warning(error,extra){this.report("warn","warning",error,extra)}warningException(error,extra){this.report("warn","warning",error,extra)}error(error,extra){this.report("error","error",error,extra)}errorException(error,extra){this.report("error","error",error,extra)}critical(error,extra){this.report("error","fatal",error,extra)}criticalException(error,extra){this.report("error","fatal",error,extra)}constructor(context){this.context=context;this.beforeReportHandlers=[]}}class SdkResult{static ok(data){return new SdkResult(true,data,undefined)}static error(error){return new SdkResult(false,undefined,error)}get isOk(){return this._success}get isError(){return!this._success}get data(){if(!this._success)throw new Error("Cannot access data on error result");return this._data}get error(){if(this._success)throw new Error("Cannot access error on success result");return this._error}constructor(_success,_data,_error){this._success=_success;this._data=_data;this._error=_error}}function createEndpointUrl(path,baseUrl){const urlString=baseUrl??window.location.href;let normalizedBase;try{const url=new URL(urlString);url.hash="";url.search="";const pathname=url.pathname;const lastSegment=pathname.split("/").pop()??"";if(lastSegment.toLowerCase().endsWith(".html")){const pathParts=pathname.split("/");pathParts.pop();url.pathname=pathParts.join("/")||"/"}normalizedBase=url.toString()}catch{normalizedBase=urlString.split("#")[0].split("?")[0]}if(normalizedBase.endsWith("/"))normalizedBase=normalizedBase.slice(0,-1);const normalizedPath=path.startsWith("/")?path:"/"+path;return normalizedBase+normalizedPath}function createEndpointUrlWithParams(path,params,baseUrl){const endpointUrl=createEndpointUrl(path,baseUrl);const url=new URL(endpointUrl);if(params){for(const[key,value]of Object.entries(params))if(value!==undefined)url.searchParams.set(key,value)}return url.toString()}const systemClock={now:()=>Date.now()};function makeCalibratedClock(nowSeconds){const driftMs=nowSeconds!=null?nowSeconds*1e3-systemClock.now():0;if(Math.abs(driftMs)<6e4)return systemClock;return{now:()=>systemClock.now()+driftMs}}const CircuitBreakerState={CLOSED:0,OPEN:1};class OpenCircuitError extends Error{constructor(lastError){super("Circuit is in open state right now. Please try again later."),this.lastError=lastError}}class CircuitBreakerImpl{trip(){this.state=1}reset(){this.state=0;this.failureCount=0}handleFailure(err){this.failureCount++;this.lastFailureTimestamp=this.clock.now();this.lastError=err;if(this.failureCount>=this.failureThreshold)this.trip()}isClosed(){return this.state===0}async call(action){if(this.state===1){if(this.lastFailureTimestamp+this.resetAfterMs>this.clock.now())throw new OpenCircuitError(this.lastError)}try{const result=await action();this.reset();return result}catch(err){this.handleFailure(err);throw err}}constructor(failureThreshold,resetAfterMs,clock=systemClock){this.failureThreshold=failureThreshold;this.resetAfterMs=resetAfterMs;this.clock=clock;this.state=0;this.failureCount=0;this.lastFailureTimestamp=0;this.lastError=undefined}}const CodeletSdkSubmission=Proto.createMessage((()=>({id:Proto.requiredString(1),data:Proto.requiredString(2)})));const CreateCodeletSdkSubmissionRequest=Proto.createMessage((()=>({data:Proto.requiredString(1),documentId:Proto.optionalString(2),elementId:Proto.optionalString(3),pageId:Proto.optionalString(6),websiteDeploymentId:Proto.optionalString(4),websiteAccessToken:Proto.optionalString(5)})));const CreateCodeletSdkSubmissionResponse=Proto.createMessage((()=>({submission:Proto.optionalObject(1,CodeletSdkSubmission)})));const FindCodeletSdkSubmissionsRequest=Proto.createMessage((()=>({documentId:Proto.optionalString(1),elementId:Proto.optionalString(2),pageId:Proto.optionalString(5),websiteDeploymentId:Proto.optionalString(3),websiteAccessToken:Proto.optionalString(4)})));const FindCodeletSdkSubmissionsResponse=Proto.createMessage((()=>({enrichedSubmissions:Proto.repeatedObject(2,CodeletSdkSubmission),pollEveryMs:Proto.optionalInt32(3)})));const UpdateCodeletSdkSubmissionRequest=Proto.createMessage((()=>({submissionId:Proto.requiredString(1),data:Proto.requiredString(2),documentId:Proto.optionalString(3),elementId:Proto.optionalString(4),pageId:Proto.optionalString(7),websiteDeploymentId:Proto.optionalString(5),websiteAccessToken:Proto.optionalString(6)})));const UpdateCodeletSdkSubmissionResponse=Proto.createMessage((()=>({})));const DeleteCodeletSdkSubmissionRequest=Proto.createMessage((()=>({submissionId:Proto.requiredString(1),documentId:Proto.optionalString(2),elementId:Proto.optionalString(3),pageId:Proto.optionalString(6),websiteDeploymentId:Proto.optionalString(4),websiteAccessToken:Proto.optionalString(5)})));const DeleteCodeletSdkSubmissionResponse=Proto.createMessage((()=>({})));const MUTATION_RATE_LIMIT_MS=500;const RATE_LIMIT_THRESHOLD=5;const CIRCUIT_BREAKER_FAILURE_THRESHOLD=5;const CIRCUIT_BREAKER_RESET_MS=3e4;class HttpError extends Error{constructor(message,status,statusText){super(message),this.status=status,this.statusText=statusText;this.name="HttpError"}}class FetchPersistenceService{checkRateLimit(){const now=Date.now();const timeSinceLastMutation=now-this.lastMutationTimestamp;if(timeSinceLastMutation=this.rateLimitThreshold){const waitTime=this.rateLimitMs-timeSinceLastMutation;throw new HttpError(`Rate limit exceeded. Please wait ${waitTime}ms before making another mutation request.`,429,"Too Many Requests")}}else this.consecutiveRateLimitBreaches=0;this.lastMutationTimestamp=now}async create(record,documentId,elementId,pageId,websiteContext){this.checkRateLimit();return this.executeMutation((async()=>{const request=new CreateCodeletSdkSubmissionRequest({data:JSON.stringify(record),documentId,elementId,pageId,websiteDeploymentId:websiteContext?.deploymentId,websiteAccessToken:websiteContext?.accessToken});const response=await fetch(createEndpointUrl("/data/create"),{method:"POST",headers:{["Content-Type"]:"application/json"},body:JSON.stringify(CreateCodeletSdkSubmissionRequest.serialize(request))});if(!response.ok)throw new HttpError(`Failed to create record: ${response.status} ${response.statusText}`,response.status,response.statusText);const responseData=await response.json();const responseProto=CreateCodeletSdkSubmissionResponse.deserialize(responseData);if(!responseProto?.submission?.id)throw new Error("Failed to create record: backend did not return an id");return{...record,__backendId:responseProto.submission.id}}))}async update(record,documentId,elementId,pageId,websiteContext){this.checkRateLimit();return this.executeMutation((async()=>{const cleanRecord={...record};delete cleanRecord.__backendId;const request=new UpdateCodeletSdkSubmissionRequest({submissionId:record.__backendId,data:JSON.stringify(cleanRecord),documentId,elementId,pageId,websiteDeploymentId:websiteContext?.deploymentId,websiteAccessToken:websiteContext?.accessToken});const response=await fetch(createEndpointUrl("/data/update"),{method:"POST",headers:{["Content-Type"]:"application/json"},body:JSON.stringify(UpdateCodeletSdkSubmissionRequest.serialize(request))});if(!response.ok)throw new HttpError(`Failed to update record: ${response.status} ${response.statusText}`,response.status,response.statusText);const responseData=await response.json();UpdateCodeletSdkSubmissionResponse.deserialize(responseData);return record}))}async delete(id,documentId,elementId,pageId,websiteContext){await this.executeMutation((async()=>{const request=new DeleteCodeletSdkSubmissionRequest({submissionId:id,documentId,elementId,pageId,websiteDeploymentId:websiteContext?.deploymentId,websiteAccessToken:websiteContext?.accessToken});const response=await fetch(createEndpointUrl("/data/remove"),{method:"POST",headers:{["Content-Type"]:"application/json"},body:JSON.stringify(DeleteCodeletSdkSubmissionRequest.serialize(request))});if(!response.ok)throw new HttpError(`Failed to delete record: ${response.status} ${response.statusText}`,response.status,response.statusText);const responseData=await response.json();DeleteCodeletSdkSubmissionResponse.deserialize(responseData)}))}async executeMutation(action){try{return await this.mutationCircuitBreaker.call(action)}catch(err){if(err instanceof OpenCircuitError){const lastErr=err.lastError;const detail=lastErr instanceof HttpError?`last error: ${lastErr.status} ${lastErr.statusText}: ${lastErr.message}`:lastErr instanceof Error?`last error: ${lastErr.message}`:"unknown error";throw new HttpError(`Mutations temporarily disabled after repeated failures (${detail}). Please try again later.`,503,"Service Unavailable")}throw err}}async read(documentId,elementId,pageId,websiteContext){const response=await fetch(createEndpointUrlWithParams("/data/getAll",{document_id:documentId,element_id:elementId,page_id:pageId,website_deployment_id:websiteContext?.deploymentId,website_access_token:websiteContext?.accessToken}),{method:"GET",headers:{["Content-Type"]:"application/json"}});if(!response.ok)throw new HttpError(`Failed to read record: ${response.status} ${response.statusText}`,response.status,response.statusText);const responseData=await response.json();const submissionData=FindCodeletSdkSubmissionsResponse.deserialize(responseData);const deserializedSubmissions=[];for(const submission of submissionData.enrichedSubmissions)try{const id=submission.id;const parsed=JSON.parse(submission.data);deserializedSubmissions.push({...parsed,__backendId:id})}catch(error){throw new Error(`Failed to parse submission: ${submission}, ${error}`)}return{submissions:deserializedSubmissions,pollingRateMs:submissionData.pollEveryMs}}constructor(rateLimitMs=MUTATION_RATE_LIMIT_MS,rateLimitThreshold=RATE_LIMIT_THRESHOLD,mutationCircuitBreaker=new CircuitBreakerImpl(CIRCUIT_BREAKER_FAILURE_THRESHOLD,CIRCUIT_BREAKER_RESET_MS)){this.rateLimitMs=rateLimitMs;this.rateLimitThreshold=rateLimitThreshold;this.mutationCircuitBreaker=mutationCircuitBreaker;this.lastMutationTimestamp=0;this.consecutiveRateLimitBreaches=0}}const TARGET_ORIGIN="*";const DEFAULT_POLLING_INTERVAL_MS=2500;const TERMINAL_POLLING_ERROR_CODES=[403,501];function areDataObjectsEqual(a,b){if(a===b)return true;const aKeys=Object.keys(a);const bKeys=Object.keys(b);if(aKeys.length!==bKeys.length)return false;for(const key of aKeys){if(!Object.prototype.hasOwnProperty.call(b,key))return false;const aValue=a[key];const bValue=b[key];if(!Object.is(aValue,bValue))return false}return true}function areDataObjectArraysEqual(a,b){if(a===b)return true;if(a.length!==b.length)return false;for(let index=0;index{try{const timeSinceLastRead=Date.now()-this.pollingState.lastReadTimestamp;if(timeSinceLastRead=5){this.errorService.error(new Error(`Stopping polling after ${this.pollingState.consecutiveErrorCount} consecutive errors.`,{cause:error}));this.pollingState.hasTerminalErrors=true;return true}this.errorService.warning(new Error(`Polling error ${this.pollingState.consecutiveErrorCount}/5`,{cause:error}));return false}resetErrorCount(){this.pollingState.consecutiveErrorCount=0}async triggerInitialReadAndReady(){try{const result=await this.read();if(!result.isOk)this.errorService.error(new Error("Failed to initialize with data",{cause:result.error}))}finally{this.commsClient?.sendRenderReady(new RenderReadyRequest)}}async init(handler){try{const setupResult=await this.setupCommsClient();if(setupResult?.isError){this.errorService.error(new Error("Failed to establish connection to parent & initialize Data SDK",{cause:setupResult.error}));return SdkResult.error(setupResult.error)}const commsClient=setupResult.data;const initRes=await commsClient.sendInitData(new InitDataRequest);const{documentId,elementId,pageId,documentExtension,websiteContext}=initRes;if(documentId)this.documentId=documentId;if(elementId)this.elementId=elementId;if(pageId&&elementId===pageId){this.pageId=pageId;this.elementId=undefined}if(documentExtension)this.documentExtension=documentExtension;if(websiteContext)this.websiteContext=websiteContext;this.dataHandler=handler;this.errorService.info("Data SDK initialized");if(initRes.isPreview&&!(initRes.documentId&&initRes.elementId)){commsClient.sendRenderReady(new RenderReadyRequest);return SdkResult.ok(undefined)}this.triggerInitialReadAndReady();if(!initRes.isPreview)this.startPolling();return SdkResult.ok(undefined)}catch(e){const error=e instanceof Error?e:new Error(String(e));return SdkResult.error(error)}}constructor(persistenceService,connectToParent,createDataClientComms,errorService){this.persistenceService=persistenceService;this.connectToParent=connectToParent;this.createDataClientComms=createDataClientComms;this.errorService=errorService;this.dataHandler=null;this.lastKnownData=[];this.pollingState={pollingInterval:null,consecutiveErrorCount:0,hasTerminalErrors:false,pollingIntervalMs:DEFAULT_POLLING_INTERVAL_MS,lastReadTimestamp:0}}}function getErrorService(){const telemetry=window.telemetrySdk?.errorService;return telemetry?.createChild("Data")??new ConsoleErrorService("Data")}window.dataSdk=new CodeletDataSdk(new FetchPersistenceService,connectToParent,(comms=>new DataClientComms(comms)),getErrorService())})();