Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@looker/embed-sdk

Package Overview
Dependencies
Maintainers
10
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@looker/embed-sdk - npm Package Compare versions

Comparing version 1.7.1-beta to 1.8.0

lib/dashboard_client.js.map

2

dist/main.js
/*! For license information please see main.js.LICENSE.txt */
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.LookerEmbedSDK=t():e.LookerEmbedSDK=t()}(self,(()=>(()=>{var e={105:function(e,t,n){"use strict";var r=this&&this.__assign||function(){return r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},r.apply(this,arguments)},o=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},i=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((o=(o=s.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyClient=t.ChattyClientStates=void 0;var s,a=n(686),u=n(346),c=n(529);n(310),function(e){e[e.Connecting=0]="Connecting",e[e.Syn=1]="Syn",e[e.Connected=2]="Connected"}(s=t.ChattyClientStates||(t.ChattyClientStates={}));var l=function(){function e(e){this._clientWindow=window,this._connection=null,this._hostWindow=this._clientWindow.parent,this._state=s.Connecting,this._sequence=0,this._receivers={},this._handlers=e.handlers,this._targetOrigin=e.targetOrigin,this._defaultTimeout=e.defaultTimeout,this._channel=new MessageChannel}return Object.defineProperty(e.prototype,"connection",{get:function(){return this._connection},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"isConnected",{get:function(){return this._state===s.Connected},enumerable:!1,configurable:!0}),e.prototype.connect=function(){return o(this,void 0,void 0,(function(){var t=this;return i(this,(function(n){return this._connection||(this._connection=new Promise((function(n,r){t._channel.port1.onmessage=function(r){switch(e._debug("received",r.data.action,r.data.data),r.data.action){case c.ChattyHostMessages.SynAck:t._state=s.Connected,t.sendMsg(u.ChattyClientMessages.Ack),n({send:function(e){for(var n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];t.sendMsg(u.ChattyClientMessages.Message,{eventName:e,payload:n})},sendAndReceive:function(e){for(var n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];return o(t,void 0,void 0,(function(){var t,r=this;return i(this,(function(o){return t=++this._sequence,this.sendMsg(u.ChattyClientMessages.MessageWithResponse,{eventName:e,payload:n},t),[2,new Promise((function(e,n){var o;r._defaultTimeout>-1&&(o=setTimeout((function(){delete r._receivers[t],n(new Error("Timeout"))}),r._defaultTimeout)),r._receivers[t]={reject:n,resolve:e,timeoutId:o}}))]}))}))}});break;case c.ChattyHostMessages.Message:t._handlers[r.data.data.eventName]&&t._handlers[r.data.data.eventName].forEach((function(e){return e.apply(t,r.data.data.payload)}));break;case c.ChattyHostMessages.MessageWithResponse:var a=r.data.data,l=a.eventName,h=a.payload,d=a.sequence,f=[];t._handlers[l]&&(f=t._handlers[l].map((function(e){return e.apply(t,h)}))),Promise.all(f).then((function(e){t.sendMsg(u.ChattyClientMessages.Response,{eventName:l,payload:e},d)})).catch((function(e){t.sendMsg(u.ChattyClientMessages.ResponseError,{eventName:l,payload:e.toString()},d)}));break;case c.ChattyHostMessages.Response:(p=t._receivers[r.data.data.sequence])&&(delete t._receivers[r.data.data.sequence],p.timeoutId&&clearTimeout(p.timeoutId),p.resolve(r.data.data.payload));break;case c.ChattyHostMessages.ResponseError:var p;(p=t._receivers[r.data.data.sequence])&&(delete t._receivers[r.data.data.sequence],p.timeoutId&&clearTimeout(p.timeoutId),p.reject("string"==typeof r.data.data.payload?new Error(r.data.data.payload):r.data.data.payload))}},t.initiateHandshake()}))),[2,this._connection]}))}))},e.prototype.initiateHandshake=function(){e._debug("connecting to",this._targetOrigin),this._hostWindow.postMessage({action:u.ChattyClientMessages.Syn},this._targetOrigin,[this._channel.port2]),this._state=s.Syn},e.prototype.sendMsg=function(t,n,o){void 0===n&&(n={});var i=o?{sequence:o}:{},s=r(r({},n),i);e._debug("sending",t,s),this._channel.port1.postMessage({action:t,data:s})},e._debug=a("looker:chatty:client"),e}();t.ChattyClient=l},955:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyClientBuilder=void 0;var r=n(105),o=function(){function e(){this._targetOrigin="*",this._handlers={},this._defaultTimeout=3e4}return Object.defineProperty(e.prototype,"targetOrigin",{get:function(){return this._targetOrigin},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"handlers",{get:function(){return this._handlers},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"defaultTimeout",{get:function(){return this._defaultTimeout},enumerable:!1,configurable:!0}),e.prototype.off=function(e,t){this._handlers[e]&&(this._handlers[e]=this._handlers[e].filter((function(e){return e!==t})))},e.prototype.on=function(e,t){return this._handlers[e]=this._handlers[e]||[],this._handlers[e].push(t),this},e.prototype.withDefaultTimeout=function(e){return this._defaultTimeout=e,this},e.prototype.withTargetOrigin=function(e){return this._targetOrigin=e,this},e.prototype.build=function(){return new r.ChattyClient(this)},e}();t.ChattyClientBuilder=o},346:(e,t)=>{"use strict";var n;Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyClientMessages=void 0,(n=t.ChattyClientMessages||(t.ChattyClientMessages={}))[n.Syn=0]="Syn",n[n.Ack=1]="Ack",n[n.Message=2]="Message",n[n.MessageWithResponse=3]="MessageWithResponse",n[n.Response=4]="Response",n[n.ResponseError=5]="ResponseError"},474:function(e,t,n){"use strict";var r=this&&this.__assign||function(){return r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},r.apply(this,arguments)},o=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},i=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((o=(o=s.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyHost=t.ChattyHostStates=void 0;var s,a=n(686),u=n(346),c=n(529);n(310),function(e){e[e.Connecting=0]="Connecting",e[e.SynAck=1]="SynAck",e[e.Connected=2]="Connected"}(s=t.ChattyHostStates||(t.ChattyHostStates={}));var l=function(){function e(e){var t=this;this._hostWindow=window,this._connection=null,this._state=s.Connecting,this._sequence=0,this._receivers={},this.iframe=document.createElement("iframe"),e.sandboxAttrs.forEach((function(e){return t.iframe.sandbox.add(e)})),"allow"in this.iframe&&(this.iframe.allow=e.allowAttrs.join("; ")),this.iframe.frameBorder=e.getFrameBorder(),e.url?this.iframe.src=e.url:e.source?this.iframe.srcdoc=e.source:console.warn("url or source required to initialize Chatty host correctly"),this._appendTo=e.el,this._handlers=e.handlers,this._port=null,this._targetOrigin=e.targetOrigin,this._defaultTimeout=e.defaultTimeout}return Object.defineProperty(e.prototype,"connection",{get:function(){return this._connection},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"isConnected",{get:function(){return this._state===s.Connected},enumerable:!1,configurable:!0}),e.prototype.connect=function(){return o(this,void 0,void 0,(function(){var t,n=this;return i(this,(function(r){return this._connection?[2,this._connection]:(t=function(){return o(n,void 0,void 0,(function(){var t=this;return i(this,(function(n){return[2,new Promise((function(n,r){var a=function(r){switch(e._debug("port received",r.data.action,r.data.data),r.data.action){case u.ChattyClientMessages.Ack:t._state=s.Connected,n({send:function(e){for(var n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];t.sendMsg(c.ChattyHostMessages.Message,{eventName:e,payload:n})},sendAndReceive:function(e){for(var n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];return o(t,void 0,void 0,(function(){var t,r=this;return i(this,(function(o){return t=++this._sequence,this.sendMsg(c.ChattyHostMessages.MessageWithResponse,{eventName:e,payload:n},t),[2,new Promise((function(e,n){var o;r._defaultTimeout>-1&&(o=setTimeout((function(){delete r._receivers[t],n(new Error("Timeout"))}),r._defaultTimeout)),r._receivers[t]={reject:n,resolve:e,timeoutId:o}}))]}))}))}});break;case u.ChattyClientMessages.Message:t._handlers[r.data.data.eventName]&&t._handlers[r.data.data.eventName].forEach((function(e){return e.apply(t,r.data.data.payload)}));break;case u.ChattyClientMessages.MessageWithResponse:var a=r.data.data,l=a.eventName,h=a.payload,d=a.sequence,f=[];t._handlers[l]&&(f=t._handlers[l].map((function(e){return e.apply(t,h)}))),Promise.all(f).then((function(e){t.sendMsg(c.ChattyHostMessages.Response,{eventName:l,payload:e},d)})).catch((function(e){t.sendMsg(c.ChattyHostMessages.ResponseError,{eventName:l,payload:e.toString()},d)}));break;case u.ChattyClientMessages.Response:(p=t._receivers[r.data.data.sequence])&&(delete t._receivers[r.data.data.sequence],p.timeoutId&&clearTimeout(p.timeoutId),p.resolve(r.data.data.payload));break;case u.ChattyClientMessages.ResponseError:var p;(p=t._receivers[r.data.data.sequence])&&(delete t._receivers[r.data.data.sequence],p.timeoutId&&clearTimeout(p.timeoutId),p.reject("string"==typeof r.data.data.payload?new Error(r.data.data.payload):r.data.data.payload))}};t._hostWindow.addEventListener("message",(function(n){if(t.isValidMsg(n)){if(e._debug("window received",n.data.action,n.data.data),n.data.action===u.ChattyClientMessages.Syn){if(t._port){if(!(t._targetOrigin&&"*"===t._targetOrigin||t._targetOrigin===n.origin))return void e._debug("rejected new connection from",n.origin);e._debug("reconnecting to",n.origin),t._port.close()}t._port=n.ports[0],t._port.onmessage=a,t.sendMsg(c.ChattyHostMessages.SynAck),t._state=s.SynAck}}else e._debug("window received invalid",n)}))}))]}))}))},this._appendTo.appendChild(this.iframe),[2,this._connection=t()])}))}))},e.prototype.sendMsg=function(t,n,o){void 0===n&&(n={});var i=o?{sequence:o}:{},s=r(r({},n),i);e._debug("sending",t,s),this._port.postMessage({action:t,data:s})},e.prototype.isValidMsg=function(e){return e.source===this.iframe.contentWindow&&(!this._targetOrigin||"*"===this._targetOrigin||this._targetOrigin===e.origin)},e._debug=a("looker:chatty:host"),e}();t.ChattyHost=l},777:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyHostBuilder=void 0;var r=n(474),o=function(){function e(e,t){this._url=e,this._source=t,this._appendTo=null,this._handlers={},this._sandboxAttrs=[],this._allowAttrs=[],this._frameBorder="0",this._targetOrigin=null,this._defaultTimeout=3e4}return Object.defineProperty(e.prototype,"el",{get:function(){return this._appendTo||document.body},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"handlers",{get:function(){return this._handlers},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"sandboxAttrs",{get:function(){return this._sandboxAttrs},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"allowAttrs",{get:function(){return this._allowAttrs},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"targetOrigin",{get:function(){return this._targetOrigin},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"url",{get:function(){return this._url},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"source",{get:function(){return this._source},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"defaultTimeout",{get:function(){return this._defaultTimeout},enumerable:!1,configurable:!0}),e.prototype.appendTo=function(e){return this._appendTo=e,this},e.prototype.off=function(e,t){this._handlers[e]&&(this._handlers[e]=this._handlers[e].filter((function(e){return e!==t})))},e.prototype.on=function(e,t){return this._handlers[e]=this._handlers[e]||[],this._handlers[e].push(t),this},e.prototype.withDefaultTimeout=function(e){return this._defaultTimeout=e,this},e.prototype.getFrameBorder=function(){return this._frameBorder},e.prototype.frameBorder=function(e){return this._frameBorder=e,this},e.prototype.sandbox=function(e){return this.withSandboxAttribute(e),this},e.prototype.withSandboxAttribute=function(e){return this._sandboxAttrs.push(e),this},e.prototype.withAllowAttribute=function(e){return this._allowAttrs.push(e),this},e.prototype.withTargetOrigin=function(e){return this._targetOrigin=e,this},e.prototype.build=function(){return new r.ChattyHost(this)},e}();t.ChattyHostBuilder=o},529:(e,t)=>{"use strict";var n;Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyHostMessages=void 0,(n=t.ChattyHostMessages||(t.ChattyHostMessages={}))[n.SynAck=0]="SynAck",n[n.Message=1]="Message",n[n.MessageWithResponse=2]="MessageWithResponse",n[n.Response=3]="Response",n[n.ResponseError=4]="ResponseError"},541:function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var o=Object.getOwnPropertyDescriptor(t,n);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,o)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||r(t,e,n)};Object.defineProperty(t,"__esModule",{value:!0}),t.Chatty=t.ChattyHost=t.ChattyClient=t.ChattyHostBuilder=t.ChattyClientBuilder=void 0;var i=n(955),s=n(777),a=n(955);Object.defineProperty(t,"ChattyClientBuilder",{enumerable:!0,get:function(){return a.ChattyClientBuilder}});var u=n(777);Object.defineProperty(t,"ChattyHostBuilder",{enumerable:!0,get:function(){return u.ChattyHostBuilder}});var c=n(105);Object.defineProperty(t,"ChattyClient",{enumerable:!0,get:function(){return c.ChattyClient}});var l=n(474);Object.defineProperty(t,"ChattyHost",{enumerable:!0,get:function(){return l.ChattyHost}}),o(n(248),t);var h=function(){function e(){}return e.createHost=function(e){return new s.ChattyHostBuilder(e)},e.createHostFromSource=function(e){return new s.ChattyHostBuilder(void 0,e)},e.createClient=function(){return new i.ChattyClientBuilder},e}();t.Chatty=h},248:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0})},686:(e,t,n)=>{function r(){var e;try{e=t.storage.debug}catch(e){}return!e&&"undefined"!=typeof process&&"env"in process&&(e=process.env.DEBUG),e}(t=e.exports=n(514)).log=function(){return"object"==typeof console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)},t.formatArgs=function(e){var n=this.useColors;if(e[0]=(n?"%c":"")+this.namespace+(n?" %c":" ")+e[0]+(n?"%c ":" ")+"+"+t.humanize(this.diff),n){var r="color: "+this.color;e.splice(1,0,r,"color: inherit");var o=0,i=0;e[0].replace(/%[a-zA-Z%]/g,(function(e){"%%"!==e&&(o++,"%c"===e&&(i=o))})),e.splice(i,0,r)}},t.save=function(e){try{null==e?t.storage.removeItem("debug"):t.storage.debug=e}catch(e){}},t.load=r,t.useColors=function(){return!("undefined"==typeof window||!window.process||"renderer"!==window.process.type)||("undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/))},t.storage="undefined"!=typeof chrome&&void 0!==chrome.storage?chrome.storage.local:function(){try{return window.localStorage}catch(e){}}(),t.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"],t.formatters.j=function(e){try{return JSON.stringify(e)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}},t.enable(r())},514:(e,t,n)=>{var r;function o(e){function n(){if(n.enabled){var e=n,o=+new Date,i=o-(r||o);e.diff=i,e.prev=r,e.curr=o,r=o;for(var s=new Array(arguments.length),a=0;a<s.length;a++)s[a]=arguments[a];s[0]=t.coerce(s[0]),"string"!=typeof s[0]&&s.unshift("%O");var u=0;s[0]=s[0].replace(/%([a-zA-Z%])/g,(function(n,r){if("%%"===n)return n;u++;var o=t.formatters[r];if("function"==typeof o){var i=s[u];n=o.call(e,i),s.splice(u,1),u--}return n})),t.formatArgs.call(e,s);var c=n.log||t.log||console.log.bind(console);c.apply(e,s)}}return n.namespace=e,n.enabled=t.enabled(e),n.useColors=t.useColors(),n.color=function(e){var n,r=0;for(n in e)r=(r<<5)-r+e.charCodeAt(n),r|=0;return t.colors[Math.abs(r)%t.colors.length]}(e),"function"==typeof t.init&&t.init(n),n}(t=e.exports=o.debug=o.default=o).coerce=function(e){return e instanceof Error?e.stack||e.message:e},t.disable=function(){t.enable("")},t.enable=function(e){t.save(e),t.names=[],t.skips=[];for(var n=("string"==typeof e?e:"").split(/[\s,]+/),r=n.length,o=0;o<r;o++)n[o]&&("-"===(e=n[o].replace(/\*/g,".*?"))[0]?t.skips.push(new RegExp("^"+e.substr(1)+"$")):t.names.push(new RegExp("^"+e+"$")))},t.enabled=function(e){var n,r;for(n=0,r=t.skips.length;n<r;n++)if(t.skips[n].test(e))return!1;for(n=0,r=t.names.length;n<r;n++)if(t.names[n].test(e))return!0;return!1},t.humanize=n(553),t.names=[],t.skips=[],t.formatters={}},553:e=>{var t=1e3,n=60*t,r=60*n,o=24*r;function i(e,t,n){if(!(e<t))return e<1.5*t?Math.floor(e/t)+" "+n:Math.ceil(e/t)+" "+n+"s"}e.exports=function(e,s){s=s||{};var a,u=typeof e;if("string"===u&&e.length>0)return function(e){if(!((e=String(e)).length>100)){var i=/^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(e);if(i){var s=parseFloat(i[1]);switch((i[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return 315576e5*s;case"days":case"day":case"d":return s*o;case"hours":case"hour":case"hrs":case"hr":case"h":return s*r;case"minutes":case"minute":case"mins":case"min":case"m":return s*n;case"seconds":case"second":case"secs":case"sec":case"s":return s*t;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return s;default:return}}}}(e);if("number"===u&&!1===isNaN(e))return s.long?i(a=e,o,"day")||i(a,r,"hour")||i(a,n,"minute")||i(a,t,"second")||a+" ms":function(e){return e>=o?Math.round(e/o)+"d":e>=r?Math.round(e/r)+"h":e>=n?Math.round(e/n)+"m":e>=t?Math.round(e/t)+"s":e+"ms"}(e);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(e))}},711:function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},r(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),i=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},s=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((o=(o=s.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedDashboard=void 0;var a=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.run=function(){this.send("dashboard:run")},t.prototype.stop=function(){this.send("dashboard:stop")},t.prototype.updateFilters=function(e){this.send("dashboard:filters:update",{filters:e})},t.prototype.setOptions=function(e){this.send("dashboard:options:set",e)},t.prototype.openScheduleDialog=function(){return i(this,void 0,void 0,(function(){return s(this,(function(e){return[2,this.sendAndReceive("dashboard:schedule_modal:open")]}))}))},t.prototype.loadDashboard=function(e,t){return void 0===t&&(t=!1),i(this,void 0,void 0,(function(){return s(this,(function(n){return[2,this.sendAndReceive("dashboard:load",{id:e,pushHistory:t})]}))}))},t}(n(211).LookerEmbedBase);t.LookerEmbedDashboard=a},354:function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((o=(o=s.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0}),t.EmbedClient=void 0;var i=n(541),s=/^https?:\/\//,a=function(){function e(e){this._builder=e,this._hostBuilder=null,this._host=null,this._connection=null,this._client=null,this._cookielessInitialized=!1,this.sessionAcquired=!1}return Object.defineProperty(e.prototype,"connection",{get:function(){return this._connection},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"isConnected",{get:function(){return!!this._connection},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"targetOrigin",{get:function(){if(this._builder.sandboxedHost)return"*";var e=this._builder.apiHost;return s.test(e)?e:"https://".concat(e)},enumerable:!1,configurable:!0}),e.prototype.createIframe=function(e){return r(this,void 0,void 0,(function(){var t,n,s,a,u,c,l,h,d,f,p=this;return o(this,(function(y){for(t in this._hostBuilder=i.Chatty.createHost(e),this._builder.isCookielessEmbed&&(this._builder.handlers["session:tokens:request"]=[function(){return r(p,void 0,void 0,(function(){var e,t,n,r,i;return o(this,(function(o){switch(o.label){case 0:return this._client&&this._cookielessApiToken&&this._builder.generateTokensCallback?this._cookielessInitialized?[4,this._builder.generateTokensCallback()]:[3,2]:[3,4];case 1:return e=o.sent(),t=e.api_token,n=e.api_token_ttl,r=e.navigation_token,i=e.navigation_token_ttl,this._cookielessApiToken=t,this._cookielessApiTokenTtl=n,this._cookielessNavigationToken=r,this._cookielessNavigationTokenTtl=i,[3,3];case 2:this._cookielessInitialized=!0,o.label=3;case 3:this._client.send("session:tokens",{api_token:this._cookielessApiToken,api_token_ttl:this._cookielessApiTokenTtl,navigation_token:this._cookielessNavigationToken,navigation_token_ttl:this._cookielessNavigationTokenTtl}),o.label=4;case 4:return[2]}}))}))}]),this._builder.handlers)for(n=function(e){s._hostBuilder.on(t,(function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];return e.apply(p._client,t)}))},s=this,a=0,u=this._builder.handlers[t];a<u.length;a++)c=u[a],n(c);for(l=0,h=this._builder.sandboxAttrs;l<h.length;l++)d=h[l],this._hostBuilder.withSandboxAttribute(d);return this._host=this._hostBuilder.frameBorder(this._builder.frameBorder).withTargetOrigin(this.targetOrigin).appendTo(this._builder.el).build(),this._builder.classNames.length&&(f=this._host.iframe.classList).add.apply(f,this._builder.classNames),[2,this._host.connect().then((function(e){return p._client=new p._builder.clientConstructor(e),p._client}))]}))}))},e.prototype.createUrl=function(){return r(this,void 0,void 0,(function(){var e,t,n,i,s,a,u=this;return o(this,(function(c){if(e=this._builder.embedUrl,!(null==(t=this._builder.auth)?void 0:t.url))return[2,"".concat(this._builder.apiHost).concat(e)];if(n="".concat(t.url,"?src=").concat(encodeURIComponent(e)),t.params)for(i=0,s=t.params;i<s.length;i++)a=s[i],n+="&".concat(encodeURIComponent(a.name),"=").concat(encodeURIComponent(a.value));return[2,new Promise((function(e,i){return r(u,void 0,void 0,(function(){var r,s,a,u;return o(this,(function(o){if((r=new XMLHttpRequest).open("GET",n),t.withCredentials&&(r.withCredentials=t.withCredentials),r.setRequestHeader("Cache-Control","no-cache"),t.headers)for(s=0,a=t.headers;s<a.length;s++)u=a[s],r.setRequestHeader(u.name,u.value);return r.onload=function(){200===r.status?e(JSON.parse(r.responseText).url):i(r.statusText)},r.onerror=function(){return i(r.statusText)},r.send(),[2]}))}))}))]}))}))},e.prototype.acquireCookielessEmbedSession=function(){return r(this,void 0,void 0,(function(){var e=this;return o(this,(function(t){switch(t.label){case 0:return this.sessionAcquired?[2,this.acquireCookielessEmbedSessionInternal()]:this.acquireSessionPromise?[4,this.acquireSessionPromise]:[3,2];case 1:return t.sent(),[2,this.acquireCookielessEmbedSessionInternal()];case 2:return this.acquireSessionPromise=this.acquireCookielessEmbedSessionInternal(),[2,this.acquireSessionPromise.then((function(t){return e.sessionAcquired=!0,t}))]}}))}))},e.prototype.acquireCookielessEmbedSessionInternal=function(){return r(this,void 0,void 0,(function(){var e,t,n,r,i,s,a,u,c,l,h,d,f;return o(this,(function(o){switch(o.label){case 0:if(e=this._builder,t=e.acquireSessionCallback,n=e.generateTokensCallback,!t)throw new Error("invalid state: acquireSessionCallback not defined");if(!n)throw new Error("invalid state: generateTokensCallback not defined");return[4,t()];case 1:if(r=o.sent(),i=r.authentication_token,s=r.api_token,a=r.api_token_ttl,u=r.navigation_token,c=r.navigation_token_ttl,!i||!u||!s)throw new Error("failed to prepare cookieless embed session");return this._cookielessApiToken=s,this._cookielessApiTokenTtl=a,this._cookielessNavigationToken=u,this._cookielessNavigationTokenTtl=c,l="https://".concat(this._builder.apiHost),h=""===new URL(this._builder.embedUrl,l).search?"?":"&",d="".concat(this._builder.embedUrl).concat(h,"embed_navigation_token=").concat(u),f="/login/embed/"+encodeURIComponent(d)+"?embed_authentication_token=".concat(i),[2,"".concat(l).concat(f)]}}))}))},e.prototype.connect=function(){return r(this,void 0,void 0,(function(){var e=this;return o(this,(function(t){return this._connection||(this._builder.url?this._connection=this.createIframe(this._builder.url):this._builder.isCookielessEmbed?this._connection=this.acquireCookielessEmbedSession().then((function(t){return r(e,void 0,void 0,(function(){return o(this,(function(e){return[2,this.createIframe(t)]}))}))})):this._connection=this.createUrl().then((function(t){return r(e,void 0,void 0,(function(){return o(this,(function(e){return[2,this.createIframe(t)]}))}))}))),[2,this._connection]}))}))},e}();t.EmbedClient=a},211:function(e,t){"use strict";var n=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},r=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((o=(o=s.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedBase=void 0;var o=function(){function e(e){this._host=e}return e.prototype.send=function(e,t){this._host.send(e,t)},e.prototype.sendAndReceive=function(e,t){return n(this,void 0,void 0,(function(){return r(this,(function(n){return[2,this._host.sendAndReceive(e,t)]}))}))},e}();t.LookerEmbedBase=o},886:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.EmbedBuilder=void 0;var r=n(354);function o(e){return e.replace(/,/g,"^,")}var i=function(){function e(e,t,n,r){if(this._hostSettings=e,this._type=t,this._endpoint=n,this._clientConstructor=r,this._handlers={},this._appendTo=null,this._sandboxAttrs=[],this._classNames=[],this._frameBorder="0",this._suffix="",this.sandboxedHost)this._params={embed_domain:this._hostSettings.apiHost,sandboxed_host:"true",sdk:"2"};else{var o=window.location.origin;this._params={embed_domain:o,sdk:"2"}}}return e.prototype.withFrameBorder=function(e){return this._frameBorder=e,this},e.prototype.withId=function(e){return this._id=e,this},e.prototype.withParams=function(e){for(var t in e)this._params[t]=e[t];return this},e.prototype.withFilters=function(e,t){if(void 0===t&&(t=!1),"dashboard"===this.type)for(var n in e)this._params[n]=t?o(e[n]):e[n];else for(var n in e)this._params["f[".concat(n,"]")]=t?o(e[n]):e[n];return this},e.prototype.withSandboxAttr=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return this._sandboxAttrs=this._sandboxAttrs.concat(e),this},e.prototype.withClassName=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return this._classNames=this._classNames.concat(e),this},e.prototype.withNext=function(e){return void 0===e&&(e="-next"),this._suffix=e,this._endpoint+=this._suffix,this},e.prototype.withTheme=function(e){return this._params.theme=e,this},e.prototype.withApiHost=function(e){if(this._hostSettings.apiHost){if(this._hostSettings.apiHost!==e)throw new Error("not allowed to change api host")}else this._hostSettings.apiHost=e,this.sandboxedHost&&(this._params.embed_domain=e,this._params.sandboxed_host="true");return this},e.prototype.withAuthUrl=function(e){var t;if(null===(t=this._hostSettings.auth)||void 0===t?void 0:t.url){if(this._hostSettings.auth.url!==e)throw new Error("not allowed to change auth url")}else this._hostSettings.auth={url:e};return this},e.prototype.withAuth=function(e){if(this._hostSettings.auth){if(this._hostSettings.auth!==e)throw new Error("not allowed to change auth")}else this._hostSettings.auth=e;return this},e.prototype.withUrl=function(e){return this._url=e,this},Object.defineProperty(e.prototype,"sandboxedHost",{get:function(){if(void 0===this._sandboxedHost){var e=window.location.origin;this._sandboxedHost="null"===e||!e}return this._sandboxedHost},set:function(e){this._sandboxedHost=e},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"el",{get:function(){return this._appendTo||document.body},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"frameBorder",{get:function(){return this._frameBorder},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"endpoint",{get:function(){return this._endpoint},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"type",{get:function(){return this._type},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"apiHost",{get:function(){return this._hostSettings.apiHost},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"isCookielessEmbed",{get:function(){return!!this._hostSettings.acquireSessionCallback},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"acquireSessionCallback",{get:function(){return this._hostSettings.acquireSessionCallback},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"generateTokensCallback",{get:function(){return this._hostSettings.generateTokensCallback},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"url",{get:function(){return this._url},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"authUrl",{get:function(){var e;return null===(e=this._hostSettings.auth)||void 0===e?void 0:e.url},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"auth",{get:function(){return this._hostSettings.auth},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"embedUrl",{get:function(){var e=function(e){var t=[];for(var n in e)t.push("".concat(encodeURIComponent(n),"=").concat(encodeURIComponent(e[n])));return t.join("&")}(this._params);return"".concat(this.endpoint,"/").concat(this.id,"?").concat(e)},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"handlers",{get:function(){return this._handlers},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"sandboxAttrs",{get:function(){return this._sandboxAttrs},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"classNames",{get:function(){return this._classNames},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"suffix",{get:function(){return this._suffix},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"id",{get:function(){return this._id},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"clientConstructor",{get:function(){return this._clientConstructor},enumerable:!1,configurable:!0}),e.prototype.appendTo=function(e){return this._appendTo="string"==typeof e?document.querySelector(e):e,this},e.prototype.on=function(e,t){return this._handlers[e]=this._handlers[e]?this._handlers[e]:[],this._handlers[e].push(t),this},e.prototype.build=function(){return new r.EmbedClient(this)},e}();t.EmbedBuilder=i},662:function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},r(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedExplore=void 0;var i=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.run=function(){this.send("look:run")},t.prototype.updateFilters=function(e){this.send("look:filters:update",{filters:e})},t}(n(211).LookerEmbedBase);t.LookerEmbedExplore=i},438:function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},r(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedExtension=void 0;var i=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t}(n(211).LookerEmbedBase);t.LookerEmbedExtension=i},433:function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var o=Object.getOwnPropertyDescriptor(t,n);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,o)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||r(t,e,n)};Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedSDK=void 0;var i=n(886),s=n(711),a=n(662),u=n(438),c=n(684);o(n(924),t);var l=function(){function e(){}return e.init=function(e,t){this.apiHost=e,this.auth="string"==typeof t?{url:t}:t},e.initCookieless=function(e,t,n){this.apiHost=e,this.acquireSessionCallback=t,this.generateTokensCallback=n},e.createDashboardWithUrl=function(e){return new i.EmbedBuilder(this,"dashboard","/embed/dashboards",s.LookerEmbedDashboard).withUrl(e)},e.createDashboardWithId=function(e){return new i.EmbedBuilder(this,"dashboard","/embed/dashboards",s.LookerEmbedDashboard).withId(e)},e.createExploreWithUrl=function(e){return new i.EmbedBuilder(this,"explore","/embed/explore",a.LookerEmbedExplore).withUrl(e)},e.createExploreWithId=function(e){return e=e.replace("::","/"),new i.EmbedBuilder(this,"explore","/embed/explore",a.LookerEmbedExplore).withId(e)},e.createLookWithUrl=function(e){return new i.EmbedBuilder(this,"look","/embed/looks",c.LookerEmbedLook).withUrl(e)},e.createLookWithId=function(e){return new i.EmbedBuilder(this,"look","/embed/looks",c.LookerEmbedLook).withId(e)},e.createExtensionWithUrl=function(e){return new i.EmbedBuilder(this,"extension","/embed/extensions",u.LookerEmbedExtension).withUrl(e)},e.createExtensionWithId=function(e){return new i.EmbedBuilder(this,"extension","/embed/extensions",u.LookerEmbedExtension).withId(e)},e}();t.LookerEmbedSDK=l},684:function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},r(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedLook=void 0;var i=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.run=function(){this.send("look:run")},t.prototype.updateFilters=function(e){this.send("look:filters:update",{filters:e})},t}(n(211).LookerEmbedBase);t.LookerEmbedLook=i},924:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0})},310:(e,t,n)=>{"use strict";e.exports=n(702).polyfill()},702:function(e,t,n){e.exports=function(){"use strict";function e(e){return"function"==typeof e}var t=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},r=0,o=void 0,i=void 0,s=function(e,t){f[r]=e,f[r+1]=t,2===(r+=2)&&(i?i(p):v())};var a="undefined"!=typeof window?window:void 0,u=a||{},c=u.MutationObserver||u.WebKitMutationObserver,l="undefined"==typeof self&&"undefined"!=typeof process&&"[object process]"==={}.toString.call(process),h="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel;function d(){var e=setTimeout;return function(){return e(p,1)}}var f=new Array(1e3);function p(){for(var e=0;e<r;e+=2)(0,f[e])(f[e+1]),f[e]=void 0,f[e+1]=void 0;r=0}var y,b,_,g,v=void 0;function m(e,t){var n=this,r=new this.constructor(C);void 0===r[k]&&B(r);var o=n._state;if(o){var i=arguments[o-1];s((function(){return A(o,r,i,n._result)}))}else M(n,r,e,t);return r}function w(e){if(e&&"object"==typeof e&&e.constructor===this)return e;var t=new this(C);return E(t,e),t}v=l?function(){return process.nextTick(p)}:c?(b=0,_=new c(p),g=document.createTextNode(""),_.observe(g,{characterData:!0}),function(){g.data=b=++b%2}):h?((y=new MessageChannel).port1.onmessage=p,function(){return y.port2.postMessage(0)}):void 0===a?function(){try{var e=Function("return this")().require("vertx");return void 0!==(o=e.runOnLoop||e.runOnContext)?function(){o(p)}:d()}catch(e){return d()}}():d();var k=Math.random().toString(36).substring(2);function C(){}var O=void 0;function x(t,n,r){n.constructor===t.constructor&&r===m&&n.constructor.resolve===w?function(e,t){1===t._state?P(e,t._result):2===t._state?S(e,t._result):M(t,void 0,(function(t){return E(e,t)}),(function(t){return S(e,t)}))}(t,n):void 0===r?P(t,n):e(r)?function(e,t,n){s((function(e){var r=!1,o=function(e,t,n,r){try{e.call(t,n,r)}catch(e){return e}}(n,t,(function(n){r||(r=!0,t!==n?E(e,n):P(e,n))}),(function(t){r||(r=!0,S(e,t))}),e._label);!r&&o&&(r=!0,S(e,o))}),e)}(t,n,r):P(t,n)}function E(e,t){if(e===t)S(e,new TypeError("You cannot resolve a promise with itself"));else if(o=typeof(r=t),null===r||"object"!==o&&"function"!==o)P(e,t);else{var n=void 0;try{n=t.then}catch(t){return void S(e,t)}x(e,t,n)}var r,o}function j(e){e._onerror&&e._onerror(e._result),T(e)}function P(e,t){e._state===O&&(e._result=t,e._state=1,0!==e._subscribers.length&&s(T,e))}function S(e,t){e._state===O&&(e._state=2,e._result=t,s(j,e))}function M(e,t,n,r){var o=e._subscribers,i=o.length;e._onerror=null,o[i]=t,o[i+1]=n,o[i+2]=r,0===i&&e._state&&s(T,e)}function T(e){var t=e._subscribers,n=e._state;if(0!==t.length){for(var r=void 0,o=void 0,i=e._result,s=0;s<t.length;s+=3)r=t[s],o=t[s+n],r?A(n,r,o,i):o(i);e._subscribers.length=0}}function A(t,n,r,o){var i=e(r),s=void 0,a=void 0,u=!0;if(i){try{s=r(o)}catch(e){u=!1,a=e}if(n===s)return void S(n,new TypeError("A promises callback cannot return that same promise."))}else s=o;n._state!==O||(i&&u?E(n,s):!1===u?S(n,a):1===t?P(n,s):2===t&&S(n,s))}var H=0;function B(e){e[k]=H++,e._state=void 0,e._result=void 0,e._subscribers=[]}var R=function(){function e(e,n){this._instanceConstructor=e,this.promise=new e(C),this.promise[k]||B(this.promise),t(n)?(this.length=n.length,this._remaining=n.length,this._result=new Array(this.length),0===this.length?P(this.promise,this._result):(this.length=this.length||0,this._enumerate(n),0===this._remaining&&P(this.promise,this._result))):S(this.promise,new Error("Array Methods must be provided an Array"))}return e.prototype._enumerate=function(e){for(var t=0;this._state===O&&t<e.length;t++)this._eachEntry(e[t],t)},e.prototype._eachEntry=function(e,t){var n=this._instanceConstructor,r=n.resolve;if(r===w){var o=void 0,i=void 0,s=!1;try{o=e.then}catch(e){s=!0,i=e}if(o===m&&e._state!==O)this._settledAt(e._state,t,e._result);else if("function"!=typeof o)this._remaining--,this._result[t]=e;else if(n===q){var a=new n(C);s?S(a,i):x(a,e,o),this._willSettleAt(a,t)}else this._willSettleAt(new n((function(t){return t(e)})),t)}else this._willSettleAt(r(e),t)},e.prototype._settledAt=function(e,t,n){var r=this.promise;r._state===O&&(this._remaining--,2===e?S(r,n):this._result[t]=n),0===this._remaining&&P(r,this._result)},e.prototype._willSettleAt=function(e,t){var n=this;M(e,void 0,(function(e){return n._settledAt(1,t,e)}),(function(e){return n._settledAt(2,t,e)}))},e}();var q=function(){function t(e){this[k]=H++,this._result=this._state=void 0,this._subscribers=[],C!==e&&("function"!=typeof e&&function(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}(),this instanceof t?function(e,t){try{t((function(t){E(e,t)}),(function(t){S(e,t)}))}catch(t){S(e,t)}}(this,e):function(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}())}return t.prototype.catch=function(e){return this.then(null,e)},t.prototype.finally=function(t){var n=this,r=n.constructor;return e(t)?n.then((function(e){return r.resolve(t()).then((function(){return e}))}),(function(e){return r.resolve(t()).then((function(){throw e}))})):n.then(t,t)},t}();return q.prototype.then=m,q.all=function(e){return new R(this,e).promise},q.race=function(e){var n=this;return t(e)?new n((function(t,r){for(var o=e.length,i=0;i<o;i++)n.resolve(e[i]).then(t,r)})):new n((function(e,t){return t(new TypeError("You must pass an array to race."))}))},q.resolve=w,q.reject=function(e){var t=new this(C);return S(t,e),t},q._setScheduler=function(e){i=e},q._setAsap=function(e){s=e},q._asap=s,q.polyfill=function(){var e=void 0;if(void 0!==n.g)e=n.g;else if("undefined"!=typeof self)e=self;else try{e=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var t=e.Promise;if(t){var r=null;try{r=Object.prototype.toString.call(t.resolve())}catch(e){}if("[object Promise]"===r&&!t.cast)return}e.Promise=q},q.Promise=q,q}()}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var i=t[r]={exports:{}};return e[r].call(i.exports,i,i.exports,n),i.exports}return n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n(433)})()));
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.LookerEmbedSDK=t():e.LookerEmbedSDK=t()}(self,(()=>(()=>{var e={105:function(e,t,n){"use strict";var r=this&&this.__assign||function(){return r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},r.apply(this,arguments)},o=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},i=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((o=(o=s.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyClient=t.ChattyClientStates=void 0;var s,a=n(686),u=n(346),c=n(529);n(310),function(e){e[e.Connecting=0]="Connecting",e[e.Syn=1]="Syn",e[e.Connected=2]="Connected"}(s=t.ChattyClientStates||(t.ChattyClientStates={}));var l=function(){function e(e){this._clientWindow=window,this._connection=null,this._hostWindow=this._clientWindow.parent,this._state=s.Connecting,this._sequence=0,this._receivers={},this._handlers=e.handlers,this._targetOrigin=e.targetOrigin,this._defaultTimeout=e.defaultTimeout,this._channel=new MessageChannel}return Object.defineProperty(e.prototype,"connection",{get:function(){return this._connection},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"isConnected",{get:function(){return this._state===s.Connected},enumerable:!1,configurable:!0}),e.prototype.connect=function(){return o(this,void 0,void 0,(function(){var t=this;return i(this,(function(n){return this._connection||(this._connection=new Promise((function(n,r){t._channel.port1.onmessage=function(r){switch(e._debug("received",r.data.action,r.data.data),r.data.action){case c.ChattyHostMessages.SynAck:t._state=s.Connected,t.sendMsg(u.ChattyClientMessages.Ack),n({send:function(e){for(var n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];t.sendMsg(u.ChattyClientMessages.Message,{eventName:e,payload:n})},sendAndReceive:function(e){for(var n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];return o(t,void 0,void 0,(function(){var t,r=this;return i(this,(function(o){return t=++this._sequence,this.sendMsg(u.ChattyClientMessages.MessageWithResponse,{eventName:e,payload:n},t),[2,new Promise((function(e,n){var o;r._defaultTimeout>-1&&(o=setTimeout((function(){delete r._receivers[t],n(new Error("Timeout"))}),r._defaultTimeout)),r._receivers[t]={reject:n,resolve:e,timeoutId:o}}))]}))}))}});break;case c.ChattyHostMessages.Message:t._handlers[r.data.data.eventName]&&t._handlers[r.data.data.eventName].forEach((function(e){return e.apply(t,r.data.data.payload)}));break;case c.ChattyHostMessages.MessageWithResponse:var a=r.data.data,l=a.eventName,h=a.payload,d=a.sequence,f=[];t._handlers[l]&&(f=t._handlers[l].map((function(e){return e.apply(t,h)}))),Promise.all(f).then((function(e){t.sendMsg(u.ChattyClientMessages.Response,{eventName:l,payload:e},d)})).catch((function(e){t.sendMsg(u.ChattyClientMessages.ResponseError,{eventName:l,payload:e.toString()},d)}));break;case c.ChattyHostMessages.Response:(p=t._receivers[r.data.data.sequence])&&(delete t._receivers[r.data.data.sequence],p.timeoutId&&clearTimeout(p.timeoutId),p.resolve(r.data.data.payload));break;case c.ChattyHostMessages.ResponseError:var p;(p=t._receivers[r.data.data.sequence])&&(delete t._receivers[r.data.data.sequence],p.timeoutId&&clearTimeout(p.timeoutId),p.reject("string"==typeof r.data.data.payload?new Error(r.data.data.payload):r.data.data.payload))}},t.initiateHandshake()}))),[2,this._connection]}))}))},e.prototype.initiateHandshake=function(){e._debug("connecting to",this._targetOrigin),this._hostWindow.postMessage({action:u.ChattyClientMessages.Syn},this._targetOrigin,[this._channel.port2]),this._state=s.Syn},e.prototype.sendMsg=function(t,n,o){void 0===n&&(n={});var i=o?{sequence:o}:{},s=r(r({},n),i);e._debug("sending",t,s),this._channel.port1.postMessage({action:t,data:s})},e._debug=a("looker:chatty:client"),e}();t.ChattyClient=l},955:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyClientBuilder=void 0;var r=n(105),o=function(){function e(){this._targetOrigin="*",this._handlers={},this._defaultTimeout=3e4}return Object.defineProperty(e.prototype,"targetOrigin",{get:function(){return this._targetOrigin},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"handlers",{get:function(){return this._handlers},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"defaultTimeout",{get:function(){return this._defaultTimeout},enumerable:!1,configurable:!0}),e.prototype.off=function(e,t){this._handlers[e]&&(this._handlers[e]=this._handlers[e].filter((function(e){return e!==t})))},e.prototype.on=function(e,t){return this._handlers[e]=this._handlers[e]||[],this._handlers[e].push(t),this},e.prototype.withDefaultTimeout=function(e){return this._defaultTimeout=e,this},e.prototype.withTargetOrigin=function(e){return this._targetOrigin=e,this},e.prototype.build=function(){return new r.ChattyClient(this)},e}();t.ChattyClientBuilder=o},346:(e,t)=>{"use strict";var n;Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyClientMessages=void 0,(n=t.ChattyClientMessages||(t.ChattyClientMessages={}))[n.Syn=0]="Syn",n[n.Ack=1]="Ack",n[n.Message=2]="Message",n[n.MessageWithResponse=3]="MessageWithResponse",n[n.Response=4]="Response",n[n.ResponseError=5]="ResponseError"},474:function(e,t,n){"use strict";var r=this&&this.__assign||function(){return r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},r.apply(this,arguments)},o=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},i=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((o=(o=s.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyHost=t.ChattyHostStates=void 0;var s,a=n(686),u=n(346),c=n(529);n(310),function(e){e[e.Connecting=0]="Connecting",e[e.SynAck=1]="SynAck",e[e.Connected=2]="Connected"}(s=t.ChattyHostStates||(t.ChattyHostStates={}));var l=function(){function e(e){var t=this;this._hostWindow=window,this._connection=null,this._state=s.Connecting,this._sequence=0,this._receivers={},this.iframe=document.createElement("iframe"),e.sandboxAttrs.forEach((function(e){return t.iframe.sandbox.add(e)})),"allow"in this.iframe&&(this.iframe.allow=e.allowAttrs.join("; ")),this.iframe.frameBorder=e.getFrameBorder(),e.url?this.iframe.src=e.url:e.source?this.iframe.srcdoc=e.source:console.warn("url or source required to initialize Chatty host correctly"),this._appendTo=e.el,this._handlers=e.handlers,this._port=null,this._targetOrigin=e.targetOrigin,this._defaultTimeout=e.defaultTimeout}return Object.defineProperty(e.prototype,"connection",{get:function(){return this._connection},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"isConnected",{get:function(){return this._state===s.Connected},enumerable:!1,configurable:!0}),e.prototype.connect=function(){return o(this,void 0,void 0,(function(){var t,n=this;return i(this,(function(r){return this._connection?[2,this._connection]:(t=function(){return o(n,void 0,void 0,(function(){var t=this;return i(this,(function(n){return[2,new Promise((function(n,r){var a=function(r){switch(e._debug("port received",r.data.action,r.data.data),r.data.action){case u.ChattyClientMessages.Ack:t._state=s.Connected,n({send:function(e){for(var n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];t.sendMsg(c.ChattyHostMessages.Message,{eventName:e,payload:n})},sendAndReceive:function(e){for(var n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];return o(t,void 0,void 0,(function(){var t,r=this;return i(this,(function(o){return t=++this._sequence,this.sendMsg(c.ChattyHostMessages.MessageWithResponse,{eventName:e,payload:n},t),[2,new Promise((function(e,n){var o;r._defaultTimeout>-1&&(o=setTimeout((function(){delete r._receivers[t],n(new Error("Timeout"))}),r._defaultTimeout)),r._receivers[t]={reject:n,resolve:e,timeoutId:o}}))]}))}))}});break;case u.ChattyClientMessages.Message:t._handlers[r.data.data.eventName]&&t._handlers[r.data.data.eventName].forEach((function(e){return e.apply(t,r.data.data.payload)}));break;case u.ChattyClientMessages.MessageWithResponse:var a=r.data.data,l=a.eventName,h=a.payload,d=a.sequence,f=[];t._handlers[l]&&(f=t._handlers[l].map((function(e){return e.apply(t,h)}))),Promise.all(f).then((function(e){t.sendMsg(c.ChattyHostMessages.Response,{eventName:l,payload:e},d)})).catch((function(e){t.sendMsg(c.ChattyHostMessages.ResponseError,{eventName:l,payload:e.toString()},d)}));break;case u.ChattyClientMessages.Response:(p=t._receivers[r.data.data.sequence])&&(delete t._receivers[r.data.data.sequence],p.timeoutId&&clearTimeout(p.timeoutId),p.resolve(r.data.data.payload));break;case u.ChattyClientMessages.ResponseError:var p;(p=t._receivers[r.data.data.sequence])&&(delete t._receivers[r.data.data.sequence],p.timeoutId&&clearTimeout(p.timeoutId),p.reject("string"==typeof r.data.data.payload?new Error(r.data.data.payload):r.data.data.payload))}};t._hostWindow.addEventListener("message",(function(n){if(t.isValidMsg(n)){if(e._debug("window received",n.data.action,n.data.data),n.data.action===u.ChattyClientMessages.Syn){if(t._port){if(!(t._targetOrigin&&"*"===t._targetOrigin||t._targetOrigin===n.origin))return void e._debug("rejected new connection from",n.origin);e._debug("reconnecting to",n.origin),t._port.close()}t._port=n.ports[0],t._port.onmessage=a,t.sendMsg(c.ChattyHostMessages.SynAck),t._state=s.SynAck}}else e._debug("window received invalid",n)}))}))]}))}))},this._appendTo.appendChild(this.iframe),[2,this._connection=t()])}))}))},e.prototype.sendMsg=function(t,n,o){void 0===n&&(n={});var i=o?{sequence:o}:{},s=r(r({},n),i);e._debug("sending",t,s),this._port.postMessage({action:t,data:s})},e.prototype.isValidMsg=function(e){return e.source===this.iframe.contentWindow&&(!this._targetOrigin||"*"===this._targetOrigin||this._targetOrigin===e.origin)},e._debug=a("looker:chatty:host"),e}();t.ChattyHost=l},777:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyHostBuilder=void 0;var r=n(474),o=function(){function e(e,t){this._url=e,this._source=t,this._appendTo=null,this._handlers={},this._sandboxAttrs=[],this._allowAttrs=[],this._frameBorder="0",this._targetOrigin=null,this._defaultTimeout=3e4}return Object.defineProperty(e.prototype,"el",{get:function(){return this._appendTo||document.body},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"handlers",{get:function(){return this._handlers},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"sandboxAttrs",{get:function(){return this._sandboxAttrs},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"allowAttrs",{get:function(){return this._allowAttrs},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"targetOrigin",{get:function(){return this._targetOrigin},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"url",{get:function(){return this._url},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"source",{get:function(){return this._source},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"defaultTimeout",{get:function(){return this._defaultTimeout},enumerable:!1,configurable:!0}),e.prototype.appendTo=function(e){return this._appendTo=e,this},e.prototype.off=function(e,t){this._handlers[e]&&(this._handlers[e]=this._handlers[e].filter((function(e){return e!==t})))},e.prototype.on=function(e,t){return this._handlers[e]=this._handlers[e]||[],this._handlers[e].push(t),this},e.prototype.withDefaultTimeout=function(e){return this._defaultTimeout=e,this},e.prototype.getFrameBorder=function(){return this._frameBorder},e.prototype.frameBorder=function(e){return this._frameBorder=e,this},e.prototype.sandbox=function(e){return this.withSandboxAttribute(e),this},e.prototype.withSandboxAttribute=function(e){return this._sandboxAttrs.push(e),this},e.prototype.withAllowAttribute=function(e){return this._allowAttrs.push(e),this},e.prototype.withTargetOrigin=function(e){return this._targetOrigin=e,this},e.prototype.build=function(){return new r.ChattyHost(this)},e}();t.ChattyHostBuilder=o},529:(e,t)=>{"use strict";var n;Object.defineProperty(t,"__esModule",{value:!0}),t.ChattyHostMessages=void 0,(n=t.ChattyHostMessages||(t.ChattyHostMessages={}))[n.SynAck=0]="SynAck",n[n.Message=1]="Message",n[n.MessageWithResponse=2]="MessageWithResponse",n[n.Response=3]="Response",n[n.ResponseError=4]="ResponseError"},541:function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var o=Object.getOwnPropertyDescriptor(t,n);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,o)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||r(t,e,n)};Object.defineProperty(t,"__esModule",{value:!0}),t.Chatty=t.ChattyHost=t.ChattyClient=t.ChattyHostBuilder=t.ChattyClientBuilder=void 0;var i=n(955),s=n(777),a=n(955);Object.defineProperty(t,"ChattyClientBuilder",{enumerable:!0,get:function(){return a.ChattyClientBuilder}});var u=n(777);Object.defineProperty(t,"ChattyHostBuilder",{enumerable:!0,get:function(){return u.ChattyHostBuilder}});var c=n(105);Object.defineProperty(t,"ChattyClient",{enumerable:!0,get:function(){return c.ChattyClient}});var l=n(474);Object.defineProperty(t,"ChattyHost",{enumerable:!0,get:function(){return l.ChattyHost}}),o(n(248),t);var h=function(){function e(){}return e.createHost=function(e){return new s.ChattyHostBuilder(e)},e.createHostFromSource=function(e){return new s.ChattyHostBuilder(void 0,e)},e.createClient=function(){return new i.ChattyClientBuilder},e}();t.Chatty=h},248:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0})},686:(e,t,n)=>{function r(){var e;try{e=t.storage.debug}catch(e){}return!e&&"undefined"!=typeof process&&"env"in process&&(e=process.env.DEBUG),e}(t=e.exports=n(514)).log=function(){return"object"==typeof console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)},t.formatArgs=function(e){var n=this.useColors;if(e[0]=(n?"%c":"")+this.namespace+(n?" %c":" ")+e[0]+(n?"%c ":" ")+"+"+t.humanize(this.diff),n){var r="color: "+this.color;e.splice(1,0,r,"color: inherit");var o=0,i=0;e[0].replace(/%[a-zA-Z%]/g,(function(e){"%%"!==e&&(o++,"%c"===e&&(i=o))})),e.splice(i,0,r)}},t.save=function(e){try{null==e?t.storage.removeItem("debug"):t.storage.debug=e}catch(e){}},t.load=r,t.useColors=function(){return!("undefined"==typeof window||!window.process||"renderer"!==window.process.type)||("undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/))},t.storage="undefined"!=typeof chrome&&void 0!==chrome.storage?chrome.storage.local:function(){try{return window.localStorage}catch(e){}}(),t.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"],t.formatters.j=function(e){try{return JSON.stringify(e)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}},t.enable(r())},514:(e,t,n)=>{var r;function o(e){function n(){if(n.enabled){var e=n,o=+new Date,i=o-(r||o);e.diff=i,e.prev=r,e.curr=o,r=o;for(var s=new Array(arguments.length),a=0;a<s.length;a++)s[a]=arguments[a];s[0]=t.coerce(s[0]),"string"!=typeof s[0]&&s.unshift("%O");var u=0;s[0]=s[0].replace(/%([a-zA-Z%])/g,(function(n,r){if("%%"===n)return n;u++;var o=t.formatters[r];if("function"==typeof o){var i=s[u];n=o.call(e,i),s.splice(u,1),u--}return n})),t.formatArgs.call(e,s);var c=n.log||t.log||console.log.bind(console);c.apply(e,s)}}return n.namespace=e,n.enabled=t.enabled(e),n.useColors=t.useColors(),n.color=function(e){var n,r=0;for(n in e)r=(r<<5)-r+e.charCodeAt(n),r|=0;return t.colors[Math.abs(r)%t.colors.length]}(e),"function"==typeof t.init&&t.init(n),n}(t=e.exports=o.debug=o.default=o).coerce=function(e){return e instanceof Error?e.stack||e.message:e},t.disable=function(){t.enable("")},t.enable=function(e){t.save(e),t.names=[],t.skips=[];for(var n=("string"==typeof e?e:"").split(/[\s,]+/),r=n.length,o=0;o<r;o++)n[o]&&("-"===(e=n[o].replace(/\*/g,".*?"))[0]?t.skips.push(new RegExp("^"+e.substr(1)+"$")):t.names.push(new RegExp("^"+e+"$")))},t.enabled=function(e){var n,r;for(n=0,r=t.skips.length;n<r;n++)if(t.skips[n].test(e))return!1;for(n=0,r=t.names.length;n<r;n++)if(t.names[n].test(e))return!0;return!1},t.humanize=n(553),t.names=[],t.skips=[],t.formatters={}},553:e=>{var t=1e3,n=60*t,r=60*n,o=24*r;function i(e,t,n){if(!(e<t))return e<1.5*t?Math.floor(e/t)+" "+n:Math.ceil(e/t)+" "+n+"s"}e.exports=function(e,s){s=s||{};var a,u=typeof e;if("string"===u&&e.length>0)return function(e){if(!((e=String(e)).length>100)){var i=/^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(e);if(i){var s=parseFloat(i[1]);switch((i[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return 315576e5*s;case"days":case"day":case"d":return s*o;case"hours":case"hour":case"hrs":case"hr":case"h":return s*r;case"minutes":case"minute":case"mins":case"min":case"m":return s*n;case"seconds":case"second":case"secs":case"sec":case"s":return s*t;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return s;default:return}}}}(e);if("number"===u&&!1===isNaN(e))return s.long?i(a=e,o,"day")||i(a,r,"hour")||i(a,n,"minute")||i(a,t,"second")||a+" ms":function(e){return e>=o?Math.round(e/o)+"d":e>=r?Math.round(e/r)+"h":e>=n?Math.round(e/n)+"m":e>=t?Math.round(e/t)+"s":e+"ms"}(e);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(e))}},711:function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},r(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),i=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},s=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((o=(o=s.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedDashboard=void 0;var a=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.run=function(){this.send("dashboard:run")},t.prototype.stop=function(){this.send("dashboard:stop")},t.prototype.edit=function(){this.send("dashboard:edit")},t.prototype.updateFilters=function(e){this.send("dashboard:filters:update",{filters:e})},t.prototype.setOptions=function(e){this.send("dashboard:options:set",e)},t.prototype.openScheduleDialog=function(){return i(this,void 0,void 0,(function(){return s(this,(function(e){return[2,this.sendAndReceive("dashboard:schedule_modal:open")]}))}))},t.prototype.loadDashboard=function(e,t){return void 0===t&&(t=!1),i(this,void 0,void 0,(function(){return s(this,(function(n){return[2,this.sendAndReceive("dashboard:load",{id:e,pushHistory:t})]}))}))},t}(n(211).LookerEmbedBase);t.LookerEmbedDashboard=a},354:function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((o=(o=s.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}},i=this&&this.__rest||function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(r=Object.getOwnPropertySymbols(e);o<r.length;o++)t.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(e,r[o])&&(n[r[o]]=e[r[o]])}return n};Object.defineProperty(t,"__esModule",{value:!0}),t.EmbedClient=void 0;var s=n(541),a=/^https?:\/\//,u=function(){function e(e){this._builder=e,this._hostBuilder=null,this._host=null,this._connection=null,this._client=null,this._cookielessInitialized=!1}return Object.defineProperty(e.prototype,"connection",{get:function(){return this._connection},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"isConnected",{get:function(){return!!this._connection},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"targetOrigin",{get:function(){if(this._builder.sandboxedHost)return"*";var e=this._builder.apiHost;return a.test(e)?e:"https://".concat(e)},enumerable:!1,configurable:!0}),e.prototype.createIframe=function(e){return r(this,void 0,void 0,(function(){var t,n,i,a,u,c,l,h,d,f,p=this;return o(this,(function(y){for(t in this._hostBuilder=s.Chatty.createHost(e),this._builder.isCookielessEmbed&&(this._builder.handlers["session:tokens:request"]=[function(){return r(p,void 0,void 0,(function(){var e,t,n,r,i,s;return o(this,(function(o){switch(o.label){case 0:return this._client&&this._cookielessApiToken&&this._builder.generateTokens?this._cookielessInitialized?[4,this.generateTokens()]:[3,2]:[3,4];case 1:return e=o.sent(),t=e.api_token,n=e.api_token_ttl,r=e.navigation_token,i=e.navigation_token_ttl,s=e.session_reference_token_ttl,this._cookielessApiToken=t,this._cookielessApiTokenTtl=n,this._cookielessNavigationToken=r,this._cookielessNavigationTokenTtl=i,this._cookielessSessionReferenceTokenTtl=s,[3,3];case 2:this._cookielessInitialized=!0,o.label=3;case 3:this._client.send("session:tokens",{api_token:this._cookielessApiToken,api_token_ttl:this._cookielessApiTokenTtl,navigation_token:this._cookielessNavigationToken,navigation_token_ttl:this._cookielessNavigationTokenTtl,session_reference_token_ttl:this._cookielessSessionReferenceTokenTtl}),o.label=4;case 4:return[2]}}))}))}]),this._builder.handlers)for(n=function(e){i._hostBuilder.on(t,(function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];return e.apply(p._client,t)}))},i=this,a=0,u=this._builder.handlers[t];a<u.length;a++)c=u[a],n(c);for(l=0,h=this._builder.sandboxAttrs;l<h.length;l++)d=h[l],this._hostBuilder.withSandboxAttribute(d);return this._host=this._hostBuilder.frameBorder(this._builder.frameBorder).withTargetOrigin(this.targetOrigin).appendTo(this._builder.el).build(),this._builder.classNames.length&&(f=this._host.iframe.classList).add.apply(f,this._builder.classNames),[2,this._host.connect().then((function(e){return p._client=new p._builder.clientConstructor(e),p._client}))]}))}))},e.prototype.createUrl=function(){return r(this,void 0,void 0,(function(){var e,t,n,i,s,a,u=this;return o(this,(function(c){if(e=this._builder.embedUrl,!(null==(t=this._builder.auth)?void 0:t.url))return[2,"".concat(this._builder.apiHost).concat(e)];if(n="".concat(t.url,"?src=").concat(encodeURIComponent(e)),t.params)for(i=0,s=t.params;i<s.length;i++)a=s[i],n+="&".concat(encodeURIComponent(a.name),"=").concat(encodeURIComponent(a.value));return[2,new Promise((function(e,i){return r(u,void 0,void 0,(function(){var r,s,a,u;return o(this,(function(o){if((r=new XMLHttpRequest).open("GET",n),t.withCredentials&&(r.withCredentials=t.withCredentials),r.setRequestHeader("Cache-Control","no-cache"),t.headers)for(s=0,a=t.headers;s<a.length;s++)u=a[s],r.setRequestHeader(u.name,u.value);return r.onload=function(){200===r.status?e(JSON.parse(r.responseText).url):i(r.statusText)},r.onerror=function(){return i(r.statusText)},r.send(),[2]}))}))}))]}))}))},e.prototype.acquireCookielessEmbedSession=function(){return r(this,void 0,void 0,(function(){return o(this,(function(t){switch(t.label){case 0:return e.sessionAcquired?[2,this.acquireCookielessEmbedSessionInternal()]:e.acquireSessionPromise?[4,e.acquireSessionPromise]:[3,2];case 1:return t.sent(),[2,this.acquireCookielessEmbedSessionInternal()];case 2:return e.acquireSessionPromise=this.acquireCookielessEmbedSessionInternal(),[2,e.acquireSessionPromise.then((function(t){return e.sessionAcquired=!0,t}))]}}))}))},e.prototype.acquireCookielessEmbedSessionInternal=function(){return r(this,void 0,void 0,(function(){var e,t,n,r,i,s,a,u,c,l,h,d,f,p;return o(this,(function(o){switch(o.label){case 0:if(e=this._builder,t=e.acquireSession,n=e.generateTokens,!t)throw new Error("invalid state: acquireSession not defined");if(!n)throw new Error("invalid state: generateTokens not defined");return[4,this.acquireSession()];case 1:if(r=o.sent(),i=r.authentication_token,s=r.api_token,a=r.api_token_ttl,u=r.navigation_token,c=r.navigation_token_ttl,l=r.session_reference_token_ttl,!i||!u||!s)throw new Error("failed to prepare cookieless embed session");return this._cookielessApiToken=s,this._cookielessApiTokenTtl=a,this._cookielessNavigationToken=u,this._cookielessNavigationTokenTtl=c,this._cookielessSessionReferenceTokenTtl=l,h="https://".concat(this._builder.apiHost),d=""===new URL(this._builder.embedUrl,h).search?"?":"&",f="".concat(this._builder.embedUrl).concat(d,"embed_navigation_token=").concat(u),p="/login/embed/"+encodeURIComponent(f)+"?embed_authentication_token=".concat(i),[2,"".concat(h).concat(p)]}}))}))},e.prototype.acquireSession=function(){return r(this,void 0,void 0,(function(){var e,t,n,r,i,s;return o(this,(function(o){switch(o.label){case 0:return"function"!=typeof(e=this._builder.acquireSession)?[3,2]:[4,e()];case 1:case 4:return[2,o.sent()];case 2:return o.trys.push([2,5,,6]),t=this.getResource(e),n=t.url,r=t.init,[4,fetch(n,r)];case 3:if(!(i=o.sent()).ok)throw console.error("acquire embed session failed",{resp:i}),new Error("acquire embed session failed");return[4,i.json()];case 5:throw s=o.sent(),console.error(s),new Error("acquire embed session failed");case 6:return[2]}}))}))},e.prototype.generateTokens=function(){return r(this,void 0,void 0,(function(){var e,t,n,r,i,s,a;return o(this,(function(o){switch(o.label){case 0:return"function"!=typeof(e=this._builder.generateTokens)?[3,2]:[4,e()];case 1:case 4:return[2,o.sent()];case 2:return o.trys.push([2,5,,6]),t=this.getResource(e),n=t.url,r=t.init,i=r||{body:JSON.stringify({api_token:this._cookielessApiToken,navigation_token:this._cookielessNavigationToken}),headers:{"content-type":"application/json"},method:"PUT"},[4,fetch(n,i)];case 3:if(!(s=o.sent()).ok){if(400===s.status)return[2,{session_reference_token_ttl:0}];throw console.error("generate tokens failed",{resp:s}),new Error("generate tokens failed")}return[4,s.json()];case 5:throw a=o.sent(),console.error(a),new Error("generate tokens failed");case 6:return[2]}}))}))},e.prototype.getResource=function(e){var t,n;if("object"==typeof e){var r=e.url;n=i(e,["url"]),t=r}else t=e;return{init:n,url:t}},e.prototype.connect=function(){return r(this,void 0,void 0,(function(){var e=this;return o(this,(function(t){if(this._connection)return[2,this._connection];if(this._builder.url){if(this._builder.isCookielessEmbed)throw new Error("withUrl not supported by cookieless embed");this._connection=this.createIframe(this._builder.url)}else this._builder.isCookielessEmbed?this._connection=this.acquireCookielessEmbedSession().then((function(t){return r(e,void 0,void 0,(function(){return o(this,(function(e){return[2,this.createIframe(t)]}))}))})):this._connection=this.createUrl().then((function(t){return r(e,void 0,void 0,(function(){return o(this,(function(e){return[2,this.createIframe(t)]}))}))}));return[2,this._connection]}))}))},e.sessionAcquired=!1,e}();t.EmbedClient=u},211:function(e,t){"use strict";var n=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function s(e){try{u(r.next(e))}catch(e){i(e)}}function a(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},r=this&&this.__generator||function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((o=(o=s.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,a])}}};Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedBase=void 0;var o=function(){function e(e){this._host=e}return e.prototype.send=function(e,t){this._host.send(e,t)},e.prototype.sendAndReceive=function(e,t){return n(this,void 0,void 0,(function(){return r(this,(function(n){return[2,this._host.sendAndReceive(e,t)]}))}))},e}();t.LookerEmbedBase=o},886:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.EmbedBuilder=void 0;var r=n(354);function o(e){return e.replace(/,/g,"^,")}var i=function(){function e(e,t,n,r){if(this._hostSettings=e,this._type=t,this._endpoint=n,this._clientConstructor=r,this._handlers={},this._appendTo=null,this._sandboxAttrs=[],this._classNames=[],this._frameBorder="0",this._suffix="",this.sandboxedHost)this._params={embed_domain:this._hostSettings.apiHost,sandboxed_host:"true",sdk:"2"};else{var o=window.location.origin;this._params={embed_domain:o,sdk:"2"}}}return e.prototype.withFrameBorder=function(e){return this._frameBorder=e,this},e.prototype.withId=function(e){return this._id=e,this},e.prototype.withParams=function(e){for(var t in e)this._params[t]=e[t];return this},e.prototype.withFilters=function(e,t){if(void 0===t&&(t=!1),"dashboard"===this.type)for(var n in e)this._params[n]=t?o(e[n]):e[n];else for(var n in e)this._params["f[".concat(n,"]")]=t?o(e[n]):e[n];return this},e.prototype.withSandboxAttr=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return this._sandboxAttrs=this._sandboxAttrs.concat(e),this},e.prototype.withClassName=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return this._classNames=this._classNames.concat(e),this},e.prototype.withNext=function(e){return void 0===e&&(e="-next"),this._suffix=e,this._endpoint+=this._suffix,this},e.prototype.withTheme=function(e){return this._params.theme=e,this},e.prototype.withApiHost=function(e){if(this._hostSettings.apiHost){if(this._hostSettings.apiHost!==e)throw new Error("not allowed to change api host")}else this._hostSettings.apiHost=e,this.sandboxedHost&&(this._params.embed_domain=e,this._params.sandboxed_host="true");return this},e.prototype.withAuthUrl=function(e){var t;if(null===(t=this._hostSettings.auth)||void 0===t?void 0:t.url){if(this._hostSettings.auth.url!==e)throw new Error("not allowed to change auth url")}else this._hostSettings.auth={url:e};return this},e.prototype.withAuth=function(e){if(this._hostSettings.auth){if(this._hostSettings.auth!==e)throw new Error("not allowed to change auth")}else this._hostSettings.auth=e;return this},e.prototype.withUrl=function(e){if(this.isCookielessEmbed)throw new Error("withUrl not supported by cookieless embed");return this._url=e,this},Object.defineProperty(e.prototype,"sandboxedHost",{get:function(){if(void 0===this._sandboxedHost){var e=window.location.origin;this._sandboxedHost="null"===e||!e}return this._sandboxedHost},set:function(e){this._sandboxedHost=e},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"el",{get:function(){return this._appendTo||document.body},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"frameBorder",{get:function(){return this._frameBorder},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"endpoint",{get:function(){return this._endpoint},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"type",{get:function(){return this._type},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"apiHost",{get:function(){return this._hostSettings.apiHost},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"isCookielessEmbed",{get:function(){return!!this._hostSettings.acquireSession},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"acquireSession",{get:function(){return this._hostSettings.acquireSession},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"generateTokens",{get:function(){return this._hostSettings.generateTokens},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"url",{get:function(){return this._url},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"authUrl",{get:function(){var e;return null===(e=this._hostSettings.auth)||void 0===e?void 0:e.url},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"auth",{get:function(){return this._hostSettings.auth},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"embedUrl",{get:function(){var e=function(e){var t=[];for(var n in e)t.push("".concat(encodeURIComponent(n),"=").concat(encodeURIComponent(e[n])));return t.join("&")}(this._params);return"".concat(this.endpoint,"/").concat(this.id,"?").concat(e)},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"handlers",{get:function(){return this._handlers},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"sandboxAttrs",{get:function(){return this._sandboxAttrs},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"classNames",{get:function(){return this._classNames},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"suffix",{get:function(){return this._suffix},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"id",{get:function(){return this._id},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"clientConstructor",{get:function(){return this._clientConstructor},enumerable:!1,configurable:!0}),e.prototype.appendTo=function(e){return this._appendTo="string"==typeof e?document.querySelector(e):e,this},e.prototype.on=function(e,t){return this._handlers[e]=this._handlers[e]?this._handlers[e]:[],this._handlers[e].push(t),this},e.prototype.build=function(){return new r.EmbedClient(this)},e}();t.EmbedBuilder=i},662:function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},r(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedExplore=void 0;var i=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.run=function(){this.send("look:run")},t.prototype.updateFilters=function(e){this.send("look:filters:update",{filters:e})},t}(n(211).LookerEmbedBase);t.LookerEmbedExplore=i},438:function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},r(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedExtension=void 0;var i=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t}(n(211).LookerEmbedBase);t.LookerEmbedExtension=i},433:function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var o=Object.getOwnPropertyDescriptor(t,n);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,o)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||r(t,e,n)};Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedSDK=void 0;var i=n(886),s=n(711),a=n(662),u=n(438),c=n(684);o(n(924),t);var l=function(){function e(){}return e.init=function(e,t){this.apiHost=e,this.auth="string"==typeof t?{url:t}:t,this.acquireSession=void 0,this.generateTokens=void 0},e.initCookieless=function(e,t,n){this.apiHost=e,this.acquireSession=t,this.generateTokens=n,this.auth=void 0},e.createDashboardWithUrl=function(e){return new i.EmbedBuilder(this,"dashboard","/embed/dashboards",s.LookerEmbedDashboard).withUrl(e)},e.createDashboardWithId=function(e){return new i.EmbedBuilder(this,"dashboard","/embed/dashboards",s.LookerEmbedDashboard).withId(e)},e.createExploreWithUrl=function(e){return new i.EmbedBuilder(this,"explore","/embed/explore",a.LookerEmbedExplore).withUrl(e)},e.createExploreWithId=function(e){return e=e.replace("::","/"),new i.EmbedBuilder(this,"explore","/embed/explore",a.LookerEmbedExplore).withId(e)},e.createLookWithUrl=function(e){return new i.EmbedBuilder(this,"look","/embed/looks",c.LookerEmbedLook).withUrl(e)},e.createLookWithId=function(e){return new i.EmbedBuilder(this,"look","/embed/looks",c.LookerEmbedLook).withId(e)},e.createExtensionWithUrl=function(e){return new i.EmbedBuilder(this,"extension","/embed/extensions",u.LookerEmbedExtension).withUrl(e)},e.createExtensionWithId=function(e){return new i.EmbedBuilder(this,"extension","/embed/extensions",u.LookerEmbedExtension).withId(e)},e}();t.LookerEmbedSDK=l},684:function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},r(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(t,"__esModule",{value:!0}),t.LookerEmbedLook=void 0;var i=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.run=function(){this.send("look:run")},t.prototype.updateFilters=function(e){this.send("look:filters:update",{filters:e})},t}(n(211).LookerEmbedBase);t.LookerEmbedLook=i},924:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0})},310:(e,t,n)=>{"use strict";e.exports=n(702).polyfill()},702:function(e,t,n){e.exports=function(){"use strict";function e(e){return"function"==typeof e}var t=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},r=0,o=void 0,i=void 0,s=function(e,t){f[r]=e,f[r+1]=t,2===(r+=2)&&(i?i(p):v())};var a="undefined"!=typeof window?window:void 0,u=a||{},c=u.MutationObserver||u.WebKitMutationObserver,l="undefined"==typeof self&&"undefined"!=typeof process&&"[object process]"==={}.toString.call(process),h="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel;function d(){var e=setTimeout;return function(){return e(p,1)}}var f=new Array(1e3);function p(){for(var e=0;e<r;e+=2)(0,f[e])(f[e+1]),f[e]=void 0,f[e+1]=void 0;r=0}var y,_,b,g,v=void 0;function m(e,t){var n=this,r=new this.constructor(C);void 0===r[k]&&B(r);var o=n._state;if(o){var i=arguments[o-1];s((function(){return A(o,r,i,n._result)}))}else T(n,r,e,t);return r}function w(e){if(e&&"object"==typeof e&&e.constructor===this)return e;var t=new this(C);return x(t,e),t}v=l?function(){return process.nextTick(p)}:c?(_=0,b=new c(p),g=document.createTextNode(""),b.observe(g,{characterData:!0}),function(){g.data=_=++_%2}):h?((y=new MessageChannel).port1.onmessage=p,function(){return y.port2.postMessage(0)}):void 0===a?function(){try{var e=Function("return this")().require("vertx");return void 0!==(o=e.runOnLoop||e.runOnContext)?function(){o(p)}:d()}catch(e){return d()}}():d();var k=Math.random().toString(36).substring(2);function C(){}var O=void 0;function E(t,n,r){n.constructor===t.constructor&&r===m&&n.constructor.resolve===w?function(e,t){1===t._state?S(e,t._result):2===t._state?P(e,t._result):T(t,void 0,(function(t){return x(e,t)}),(function(t){return P(e,t)}))}(t,n):void 0===r?S(t,n):e(r)?function(e,t,n){s((function(e){var r=!1,o=function(e,t,n,r){try{e.call(t,n,r)}catch(e){return e}}(n,t,(function(n){r||(r=!0,t!==n?x(e,n):S(e,n))}),(function(t){r||(r=!0,P(e,t))}),e._label);!r&&o&&(r=!0,P(e,o))}),e)}(t,n,r):S(t,n)}function x(e,t){if(e===t)P(e,new TypeError("You cannot resolve a promise with itself"));else if(o=typeof(r=t),null===r||"object"!==o&&"function"!==o)S(e,t);else{var n=void 0;try{n=t.then}catch(t){return void P(e,t)}E(e,t,n)}var r,o}function j(e){e._onerror&&e._onerror(e._result),M(e)}function S(e,t){e._state===O&&(e._result=t,e._state=1,0!==e._subscribers.length&&s(M,e))}function P(e,t){e._state===O&&(e._state=2,e._result=t,s(j,e))}function T(e,t,n,r){var o=e._subscribers,i=o.length;e._onerror=null,o[i]=t,o[i+1]=n,o[i+2]=r,0===i&&e._state&&s(M,e)}function M(e){var t=e._subscribers,n=e._state;if(0!==t.length){for(var r=void 0,o=void 0,i=e._result,s=0;s<t.length;s+=3)r=t[s],o=t[s+n],r?A(n,r,o,i):o(i);e._subscribers.length=0}}function A(t,n,r,o){var i=e(r),s=void 0,a=void 0,u=!0;if(i){try{s=r(o)}catch(e){u=!1,a=e}if(n===s)return void P(n,new TypeError("A promises callback cannot return that same promise."))}else s=o;n._state!==O||(i&&u?x(n,s):!1===u?P(n,a):1===t?S(n,s):2===t&&P(n,s))}var H=0;function B(e){e[k]=H++,e._state=void 0,e._result=void 0,e._subscribers=[]}var q=function(){function e(e,n){this._instanceConstructor=e,this.promise=new e(C),this.promise[k]||B(this.promise),t(n)?(this.length=n.length,this._remaining=n.length,this._result=new Array(this.length),0===this.length?S(this.promise,this._result):(this.length=this.length||0,this._enumerate(n),0===this._remaining&&S(this.promise,this._result))):P(this.promise,new Error("Array Methods must be provided an Array"))}return e.prototype._enumerate=function(e){for(var t=0;this._state===O&&t<e.length;t++)this._eachEntry(e[t],t)},e.prototype._eachEntry=function(e,t){var n=this._instanceConstructor,r=n.resolve;if(r===w){var o=void 0,i=void 0,s=!1;try{o=e.then}catch(e){s=!0,i=e}if(o===m&&e._state!==O)this._settledAt(e._state,t,e._result);else if("function"!=typeof o)this._remaining--,this._result[t]=e;else if(n===R){var a=new n(C);s?P(a,i):E(a,e,o),this._willSettleAt(a,t)}else this._willSettleAt(new n((function(t){return t(e)})),t)}else this._willSettleAt(r(e),t)},e.prototype._settledAt=function(e,t,n){var r=this.promise;r._state===O&&(this._remaining--,2===e?P(r,n):this._result[t]=n),0===this._remaining&&S(r,this._result)},e.prototype._willSettleAt=function(e,t){var n=this;T(e,void 0,(function(e){return n._settledAt(1,t,e)}),(function(e){return n._settledAt(2,t,e)}))},e}();var R=function(){function t(e){this[k]=H++,this._result=this._state=void 0,this._subscribers=[],C!==e&&("function"!=typeof e&&function(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}(),this instanceof t?function(e,t){try{t((function(t){x(e,t)}),(function(t){P(e,t)}))}catch(t){P(e,t)}}(this,e):function(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}())}return t.prototype.catch=function(e){return this.then(null,e)},t.prototype.finally=function(t){var n=this,r=n.constructor;return e(t)?n.then((function(e){return r.resolve(t()).then((function(){return e}))}),(function(e){return r.resolve(t()).then((function(){throw e}))})):n.then(t,t)},t}();return R.prototype.then=m,R.all=function(e){return new q(this,e).promise},R.race=function(e){var n=this;return t(e)?new n((function(t,r){for(var o=e.length,i=0;i<o;i++)n.resolve(e[i]).then(t,r)})):new n((function(e,t){return t(new TypeError("You must pass an array to race."))}))},R.resolve=w,R.reject=function(e){var t=new this(C);return P(t,e),t},R._setScheduler=function(e){i=e},R._setAsap=function(e){s=e},R._asap=s,R.polyfill=function(){var e=void 0;if(void 0!==n.g)e=n.g;else if("undefined"!=typeof self)e=self;else try{e=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var t=e.Promise;if(t){var r=null;try{r=Object.prototype.toString.call(t.resolve())}catch(e){}if("[object Promise]"===r&&!t.cast)return}e.Promise=R},R.Promise=R,R}()}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var i=t[r]={exports:{}};return e[r].call(i.exports,i,i.exports,n),i.exports}return n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n(433)})()));

@@ -19,2 +19,8 @@ import type { LookerDashboardOptions, LookerEmbedFilterParams } from './types';

/**
* Convenience method for sending an edit message to the embedded dashboard.
*
* Requires Looker 22.20 and Dashboards Next (see [[EmbedBuilder.withNext]]).
*/
edit(): void;
/**
* Convenience method for updating the filters of the embedded dashboard.

@@ -21,0 +27,0 @@ *

@@ -105,2 +105,10 @@ "use strict";

/**
* Convenience method for sending an edit message to the embedded dashboard.
*
* Requires Looker 22.20 and Dashboards Next (see [[EmbedBuilder.withNext]]).
*/
LookerEmbedDashboard.prototype.edit = function () {
this.send('dashboard:edit');
};
/**
* Convenience method for updating the filters of the embedded dashboard.

@@ -153,1 +161,2 @@ *

exports.LookerEmbedDashboard = LookerEmbedDashboard;
//# sourceMappingURL=dashboard_client.js.map

@@ -101,1 +101,2 @@ "use strict";

exports.LookerEmbedBase = LookerEmbedBase;
//# sourceMappingURL=embed_base.js.map
import type { ChattyHostConnection, CallbackStore } from '@looker/chatty';
import { EmbedClient } from './embed';
import type { LookerAuthConfig, LookerEmbedEventMap, LookerEmbedFilterParams, LookerEmbedCookielessSessionData } from './types';
import type { LookerAuthConfig, LookerEmbedEventMap, LookerEmbedFilterParams, CookielessCallback, CookielessRequestInit } from './types';
declare type EmbedClientConstructor<T> = {

@@ -10,6 +10,6 @@ new (host: ChattyHostConnection): T;

auth?: LookerAuthConfig;
acquireSessionCallback?: () => Promise<LookerEmbedCookielessSessionData>;
generateTokensCallback?: () => Promise<LookerEmbedCookielessSessionData>;
acquireSession?: CookielessCallback | string | CookielessRequestInit;
generateTokens?: CookielessCallback | string | CookielessRequestInit;
}
interface UrlParams {
export interface UrlParams {
[key: string]: string;

@@ -143,9 +143,9 @@ }

/**
* Cookieless embed session prepare callback
* Cookieless embed acquire session
*/
get acquireSessionCallback(): (() => Promise<LookerEmbedCookielessSessionData>) | undefined;
get acquireSession(): string | CookielessCallback | CookielessRequestInit | undefined;
/**
* Cookieless embed refresh api token callback
* Cookieless embed generate tokens
*/
get generateTokensCallback(): (() => Promise<LookerEmbedCookielessSessionData>) | undefined;
get generateTokens(): string | CookielessCallback | CookielessRequestInit | undefined;
/**

@@ -152,0 +152,0 @@ * The content URL of this embedded content, if provided

@@ -223,2 +223,5 @@ "use strict";

EmbedBuilder.prototype.withUrl = function (url) {
if (this.isCookielessEmbed) {
throw new Error('withUrl not supported by cookieless embed');
}
this._url = url;

@@ -302,3 +305,3 @@ return this;

get: function () {
return !!this._hostSettings.acquireSessionCallback;
return !!this._hostSettings.acquireSession;
},

@@ -308,8 +311,8 @@ enumerable: false,

});
Object.defineProperty(EmbedBuilder.prototype, "acquireSessionCallback", {
Object.defineProperty(EmbedBuilder.prototype, "acquireSession", {
/**
* Cookieless embed session prepare callback
* Cookieless embed acquire session
*/
get: function () {
return this._hostSettings.acquireSessionCallback;
return this._hostSettings.acquireSession;
},

@@ -319,8 +322,8 @@ enumerable: false,

});
Object.defineProperty(EmbedBuilder.prototype, "generateTokensCallback", {
Object.defineProperty(EmbedBuilder.prototype, "generateTokens", {
/**
* Cookieless embed refresh api token callback
* Cookieless embed generate tokens
*/
get: function () {
return this._hostSettings.generateTokensCallback;
return this._hostSettings.generateTokens;
},

@@ -469,1 +472,2 @@ enumerable: false,

exports.EmbedBuilder = EmbedBuilder;
//# sourceMappingURL=embed_builder.js.map

@@ -9,2 +9,4 @@ import type { ChattyHost, ChattyHostBuilder } from '@looker/chatty';

private _builder;
private static sessionAcquired;
private static acquireSessionPromise?;
_hostBuilder: ChattyHostBuilder | null;

@@ -19,2 +21,3 @@ _host: ChattyHost | null;

_cookielessNavigationTokenTtl?: number | null;
_cookielessSessionReferenceTokenTtl?: number | null;
/**

@@ -36,6 +39,7 @@ * @hidden

private createUrl;
private sessionAcquired;
private acquireSessionPromise?;
private acquireCookielessEmbedSession;
private acquireCookielessEmbedSessionInternal;
private acquireSession;
private generateTokens;
private getResource;
/**

@@ -42,0 +46,0 @@ * Establish two way communication with embedded content. Returns a promise that resolves to a

@@ -63,2 +63,13 @@ "use strict";

};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -83,3 +94,2 @@ exports.EmbedClient = void 0;

this._cookielessInitialized = false;
this.sessionAcquired = false;
}

@@ -128,3 +138,3 @@ Object.defineProperty(EmbedClient.prototype, "connection", {

function () { return __awaiter(_this, void 0, void 0, function () {
var _a, api_token, api_token_ttl, navigation_token, navigation_token_ttl, client;
var _a, api_token, api_token_ttl, navigation_token, navigation_token_ttl, session_reference_token_ttl, client;
return __generator(this, function (_b) {

@@ -135,7 +145,7 @@ switch (_b.label) {

this._cookielessApiToken &&
this._builder.generateTokensCallback)) return [3 /*break*/, 4];
this._builder.generateTokens)) return [3 /*break*/, 4];
if (!this._cookielessInitialized) return [3 /*break*/, 2];
return [4 /*yield*/, this._builder.generateTokensCallback()];
return [4 /*yield*/, this.generateTokens()];
case 1:
_a = _b.sent(), api_token = _a.api_token, api_token_ttl = _a.api_token_ttl, navigation_token = _a.navigation_token, navigation_token_ttl = _a.navigation_token_ttl;
_a = _b.sent(), api_token = _a.api_token, api_token_ttl = _a.api_token_ttl, navigation_token = _a.navigation_token, navigation_token_ttl = _a.navigation_token_ttl, session_reference_token_ttl = _a.session_reference_token_ttl;
this._cookielessApiToken = api_token;

@@ -145,2 +155,4 @@ this._cookielessApiTokenTtl = api_token_ttl;

this._cookielessNavigationTokenTtl = navigation_token_ttl;
this._cookielessSessionReferenceTokenTtl =
session_reference_token_ttl;
return [3 /*break*/, 3];

@@ -157,2 +169,3 @@ case 2:

navigation_token_ttl: this._cookielessNavigationTokenTtl,
session_reference_token_ttl: this._cookielessSessionReferenceTokenTtl,
});

@@ -254,11 +267,10 @@ _b.label = 4;

return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (this.sessionAcquired) {
if (EmbedClient.sessionAcquired) {
return [2 /*return*/, this.acquireCookielessEmbedSessionInternal()];
}
if (!this.acquireSessionPromise) return [3 /*break*/, 2];
return [4 /*yield*/, this.acquireSessionPromise];
if (!EmbedClient.acquireSessionPromise) return [3 /*break*/, 2];
return [4 /*yield*/, EmbedClient.acquireSessionPromise];
case 1:

@@ -268,5 +280,6 @@ _a.sent();

case 2:
this.acquireSessionPromise = this.acquireCookielessEmbedSessionInternal();
return [2 /*return*/, this.acquireSessionPromise.then(function (url) {
_this.sessionAcquired = true;
EmbedClient.acquireSessionPromise =
this.acquireCookielessEmbedSessionInternal();
return [2 /*return*/, EmbedClient.acquireSessionPromise.then(function (url) {
EmbedClient.sessionAcquired = true;
return url;

@@ -280,16 +293,16 @@ })];

return __awaiter(this, void 0, void 0, function () {
var _a, acquireSessionCallback, generateTokensCallback, _b, authentication_token, api_token, api_token_ttl, navigation_token, navigation_token_ttl, apiHost, sep, src, embedPath;
var _a, acquireSession, generateTokens, _b, authentication_token, api_token, api_token_ttl, navigation_token, navigation_token_ttl, session_reference_token_ttl, apiHost, sep, src, embedPath;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_a = this._builder, acquireSessionCallback = _a.acquireSessionCallback, generateTokensCallback = _a.generateTokensCallback;
if (!acquireSessionCallback) {
throw new Error('invalid state: acquireSessionCallback not defined');
_a = this._builder, acquireSession = _a.acquireSession, generateTokens = _a.generateTokens;
if (!acquireSession) {
throw new Error('invalid state: acquireSession not defined');
}
if (!generateTokensCallback) {
throw new Error('invalid state: generateTokensCallback not defined');
if (!generateTokens) {
throw new Error('invalid state: generateTokens not defined');
}
return [4 /*yield*/, acquireSessionCallback()];
return [4 /*yield*/, this.acquireSession()];
case 1:
_b = _c.sent(), authentication_token = _b.authentication_token, api_token = _b.api_token, api_token_ttl = _b.api_token_ttl, navigation_token = _b.navigation_token, navigation_token_ttl = _b.navigation_token_ttl;
_b = _c.sent(), authentication_token = _b.authentication_token, api_token = _b.api_token, api_token_ttl = _b.api_token_ttl, navigation_token = _b.navigation_token, navigation_token_ttl = _b.navigation_token_ttl, session_reference_token_ttl = _b.session_reference_token_ttl;
if (!authentication_token || !navigation_token || !api_token) {

@@ -302,2 +315,3 @@ throw new Error('failed to prepare cookieless embed session');

this._cookielessNavigationTokenTtl = navigation_token_ttl;
this._cookielessSessionReferenceTokenTtl = session_reference_token_ttl;
apiHost = "https://".concat(this._builder.apiHost);

@@ -314,2 +328,90 @@ sep = new URL(this._builder.embedUrl, apiHost).search === '' ? '?' : '&';

};
EmbedClient.prototype.acquireSession = function () {
return __awaiter(this, void 0, void 0, function () {
var acquireSession, _a, url, init, resp, error_1;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
acquireSession = this._builder.acquireSession;
if (!(typeof acquireSession === 'function')) return [3 /*break*/, 2];
return [4 /*yield*/, acquireSession()];
case 1: return [2 /*return*/, _b.sent()];
case 2:
_b.trys.push([2, 5, , 6]);
_a = this.getResource(acquireSession), url = _a.url, init = _a.init;
return [4 /*yield*/, fetch(url, init)];
case 3:
resp = _b.sent();
if (!resp.ok) {
console.error('acquire embed session failed', { resp: resp });
throw new Error("acquire embed session failed");
}
return [4 /*yield*/, resp.json()];
case 4: return [2 /*return*/, (_b.sent())];
case 5:
error_1 = _b.sent();
console.error(error_1);
throw new Error("acquire embed session failed");
case 6: return [2 /*return*/];
}
});
});
};
EmbedClient.prototype.generateTokens = function () {
return __awaiter(this, void 0, void 0, function () {
var generateTokens, _a, url, defaultInit, init, resp, error_2;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
generateTokens = this._builder.generateTokens;
if (!(typeof generateTokens === 'function')) return [3 /*break*/, 2];
return [4 /*yield*/, generateTokens()];
case 1: return [2 /*return*/, _b.sent()];
case 2:
_b.trys.push([2, 5, , 6]);
_a = this.getResource(generateTokens), url = _a.url, defaultInit = _a.init;
init = defaultInit || {
body: JSON.stringify({
api_token: this._cookielessApiToken,
navigation_token: this._cookielessNavigationToken,
}),
headers: {
'content-type': 'application/json',
},
method: 'PUT',
};
return [4 /*yield*/, fetch(url, init)];
case 3:
resp = _b.sent();
if (!resp.ok) {
if (resp.status === 400) {
return [2 /*return*/, { session_reference_token_ttl: 0 }];
}
console.error('generate tokens failed', { resp: resp });
throw new Error("generate tokens failed");
}
return [4 /*yield*/, resp.json()];
case 4: return [2 /*return*/, (_b.sent())];
case 5:
error_2 = _b.sent();
console.error(error_2);
throw new Error("generate tokens failed");
case 6: return [2 /*return*/];
}
});
});
};
EmbedClient.prototype.getResource = function (resource) {
var url;
var init;
if (typeof resource === 'object') {
var tempUrl = resource.url, rest = __rest(resource, ["url"]);
init = rest;
url = tempUrl;
}
else {
url = resource;
}
return { init: init, url: url };
};
/**

@@ -326,2 +428,5 @@ * Establish two way communication with embedded content. Returns a promise that resolves to a

if (this._builder.url) {
if (this._builder.isCookielessEmbed) {
throw new Error('withUrl not supported by cookieless embed');
}
this._connection = this.createIframe(this._builder.url);

@@ -345,4 +450,6 @@ }

};
EmbedClient.sessionAcquired = false;
return EmbedClient;
}());
exports.EmbedClient = EmbedClient;
//# sourceMappingURL=embed.js.map

@@ -71,1 +71,2 @@ "use strict";

exports.LookerEmbedExplore = LookerEmbedExplore;
//# sourceMappingURL=explore_client.js.map

@@ -57,1 +57,2 @@ "use strict";

exports.LookerEmbedExtension = LookerEmbedExtension;
//# sourceMappingURL=extension_client.js.map

@@ -6,3 +6,3 @@ import { EmbedBuilder } from './embed_builder';

import { LookerEmbedLook } from './look_client';
import type { LookerAuthConfig, LookerEmbedCookielessSessionData } from './types';
import type { LookerAuthConfig, CookielessCallback, CookielessRequestInit } from './types';
export type { LookerEmbedDashboard } from './dashboard_client';

@@ -12,2 +12,5 @@ export type { LookerEmbedExplore } from './explore_client';

export type { LookerEmbedLook } from './look_client';
export type { LookerEmbedBase } from './embed_base';
export type { EmbedBuilder, UrlParams } from './embed_builder';
export type { EmbedClient } from './embed';
export * from './types';

@@ -26,15 +29,15 @@ export declare class LookerEmbedSDK {

*
* @param apiHost The address or base URL of the Looker host (example.looker.com:9999, https://example.looker.com:9999)
* This is required for verification of messages sent from the embedded content.
* @param acquireSessionCallback A callback that will acquire a cookieless session. The `acquire_embed_cookieless_session`
* api end point should ultimately be called. The recommended approach is via a proxy endpoint provided by the hosting
* application. Two tokens are returned. The navigation token is automatically appended to Looker URLs that result in
* navigation in the embedded IFRAME. The api token is sent to the Looker Application running in the embedded IFRAME
* once the underlying chatty connection has been established.
* @param generateTokensCallback A callback that will generate new navigation and api tokens. The `generate_tokens_for_cookieless_session`
* api end point should ultimately be called. The recommended approach is via a proxy endpoint provided by the hosting
* application. The Embed SDK will call this prior to the api and navigation tokens expiring and will send the new api
* token to the embedded IFRAME.
* @param apiHost The address or base URL of the host (example.looker.com:9999, https://example.looker.com:9999)
* @param acquireSession is either a string containing a server endpoint that will acquire the embed session OR
* a RequestInfo object for a fetch call to the server endpoint that will acquire the embed session OR
* a callback that will invoke the server endpoint that will acquire the embed session.
* The server endpoint must ultimately call the Looker endpoint `acquire_embed_cookieless_session`.
* @param generateTokens is either a string containing a server endpoint that will generate new tokens OR
* a RequestInfo object for a fetch call to the server endpoint that will generate new tokens OR
* a callback that will invoke the server endpoint that will generate new tokens.
* The server endpoint should ultimately call the Looker endpoint `generate_tokens_for_cookieless_session`.
*
* Looker 22.20+
*/
static initCookieless(apiHost: string, acquireSessionCallback: () => Promise<LookerEmbedCookielessSessionData>, generateTokensCallback: () => Promise<LookerEmbedCookielessSessionData>): void;
static initCookieless(apiHost: string, acquireSession: string | CookielessRequestInit | CookielessCallback, generateTokens: string | CookielessRequestInit | CookielessCallback): void;
/**

@@ -99,7 +102,7 @@ * Create an EmbedBuilder for an embedded Looker dashboard.

*/
static acquireSessionCallback?: () => Promise<LookerEmbedCookielessSessionData>;
static acquireSession?: string | CookielessRequestInit | CookielessCallback;
/**
* @hidden
*/
static generateTokensCallback?: () => Promise<LookerEmbedCookielessSessionData>;
static generateTokens?: string | CookielessRequestInit | CookielessCallback;
}

@@ -62,2 +62,4 @@ "use strict";

this.auth = typeof auth === 'string' ? { url: auth } : auth;
this.acquireSession = undefined;
this.generateTokens = undefined;
};

@@ -67,18 +69,19 @@ /**

*
* @param apiHost The address or base URL of the Looker host (example.looker.com:9999, https://example.looker.com:9999)
* This is required for verification of messages sent from the embedded content.
* @param acquireSessionCallback A callback that will acquire a cookieless session. The `acquire_embed_cookieless_session`
* api end point should ultimately be called. The recommended approach is via a proxy endpoint provided by the hosting
* application. Two tokens are returned. The navigation token is automatically appended to Looker URLs that result in
* navigation in the embedded IFRAME. The api token is sent to the Looker Application running in the embedded IFRAME
* once the underlying chatty connection has been established.
* @param generateTokensCallback A callback that will generate new navigation and api tokens. The `generate_tokens_for_cookieless_session`
* api end point should ultimately be called. The recommended approach is via a proxy endpoint provided by the hosting
* application. The Embed SDK will call this prior to the api and navigation tokens expiring and will send the new api
* token to the embedded IFRAME.
* @param apiHost The address or base URL of the host (example.looker.com:9999, https://example.looker.com:9999)
* @param acquireSession is either a string containing a server endpoint that will acquire the embed session OR
* a RequestInfo object for a fetch call to the server endpoint that will acquire the embed session OR
* a callback that will invoke the server endpoint that will acquire the embed session.
* The server endpoint must ultimately call the Looker endpoint `acquire_embed_cookieless_session`.
* @param generateTokens is either a string containing a server endpoint that will generate new tokens OR
* a RequestInfo object for a fetch call to the server endpoint that will generate new tokens OR
* a callback that will invoke the server endpoint that will generate new tokens.
* The server endpoint should ultimately call the Looker endpoint `generate_tokens_for_cookieless_session`.
*
* Looker 22.20+
*/
LookerEmbedSDK.initCookieless = function (apiHost, acquireSessionCallback, generateTokensCallback) {
LookerEmbedSDK.initCookieless = function (apiHost, acquireSession, generateTokens) {
this.apiHost = apiHost;
this.acquireSessionCallback = acquireSessionCallback;
this.generateTokensCallback = generateTokensCallback;
this.acquireSession = acquireSession;
this.generateTokens = generateTokens;
this.auth = undefined;
};

@@ -153,1 +156,2 @@ /**

exports.LookerEmbedSDK = LookerEmbedSDK;
//# sourceMappingURL=index.js.map

@@ -71,1 +71,2 @@ "use strict";

exports.LookerEmbedLook = LookerEmbedLook;
//# sourceMappingURL=look_client.js.map

@@ -20,3 +20,16 @@ import type { LookerEmbedBase } from './embed_base';

/**
* Cookieless request init
* Looker 22.20+
*/
export interface CookielessRequestInit extends RequestInit {
url: string;
}
/**
* Cookieless request callback function
* Looker 22.20+
*/
export declare type CookielessCallback = () => Promise<LookerEmbedCookielessSessionData>;
/**
* Cookieless session data
* Looker 23.0+
*/

@@ -51,3 +64,3 @@ export interface LookerEmbedCookielessSessionData {

*/
session_ttl?: number | null;
session_reference_token_ttl?: number | null;
}

@@ -65,3 +78,3 @@ /**

*/
interface DashboardLayout {
export interface DashboardLayout {
id: string;

@@ -81,3 +94,3 @@ dashboard_id: string;

*/
interface DashboardLayoutComponent {
export interface DashboardLayoutComponent {
id: string;

@@ -134,2 +147,34 @@ dashboard_layout_id: string;

/**
* Cookieless embed session token request
* Looker 22.20+
*/
export declare type SessionTokenRequest = EventDetail;
/**
* Cookieless session status event
* Looker 23.0+
*/
export interface SessionStatus extends EventDetail {
/**
* Session time to live in seconds
*/
session_ttl: number;
/**
* Session expired when true
*/
expired: boolean;
/**
* Session interrupted when true. This means new
* tokens could not be retrieved in a timely manner.
* Can happen if server is temporarily unavailable
* for some reason
*/
interrupted: boolean;
/**
* Interrupted session can be recovered. When false
* session cannot continue. This is most likely
* a problem with the embedding application.
*/
recoverable?: boolean;
}
/**
* Detailed dashboard data returned by dashboard events

@@ -140,2 +185,3 @@ */

title: string;
canEdit: boolean;
dashboard_filters: LookerEmbedFilterParams;

@@ -267,3 +313,3 @@ absoluteUrl: string;

* Look save event details
* Looker version 21.6
* Looker version 21.6+
*/

@@ -273,3 +319,3 @@ export interface LookSaveEventDetail extends LookEventDetail {

* Folder Look is associated with
* Looker version 21.8
* Looker version 21.8+
*/

@@ -280,3 +326,3 @@ spaceId: number;

* Look save event
* Looker version 21.6
* Looker version 21.6+
*/

@@ -334,9 +380,23 @@ export interface LookSaveEvent extends LookerEmbedEvent {

/**
* Dashboard saved event
* Looker 21.6
* Dashboard editing started event.
* Not available to legacy dashboards.
* Looker 22.20+
*/
'dashboard:edit:start': (this: LookerEmbedDashboard, event: DashboardEvent) => void;
/**
* Dashboard editing cancelled event.
* Not available to legacy dashboards.
* Looker 22.20+
*/
'dashboard:edit:cancel': (this: LookerEmbedDashboard, event: DashboardEvent) => void;
/**
* Dashboard saved event. Fired when a dashboard
* being edited is saved. Use in conjunction with
* `dashboard:edit:start` and `dashboard:edit:save`.
* Looker 21.6+
*/
'dashboard:save:complete': (this: LookerEmbedDashboard, event: DashboardEvent) => void;
/**
* Dashboard deleted event
* Looker 21.6
* Looker 21.6+
*/

@@ -359,3 +419,3 @@ 'dashboard:delete:complete': (this: LookerEmbedDashboard, event: DashboardEvent) => void;

* Look saved event
* Looker 21.6
* Looker 21.6+
*/

@@ -365,3 +425,3 @@ 'look:save:complete': (this: LookerEmbedLook, event: LookSaveEvent) => void;

* Look deleted event
* Looker 21.6
* Looker 21.6+
*/

@@ -373,4 +433,13 @@ 'look:delete:complete': (this: LookerEmbedLook, event: LookSaveEvent) => void;

'page:properties:changed': (this: LookerEmbedBase, event: PagePropertiesChangedEvent) => void;
/**
* Cookieless embed session tokens request event
* Looker 22.20+
*/
'session:token:request': (this: LookerEmbedBase, event: SessionTokenRequest) => void;
/**
* Cookieless embed session status event
* Looker 23.0+
*/
'session:status': (this: LookerEmbedBase, event: SessionStatus) => void;
[key: string]: any;
}
export {};

@@ -28,1 +28,2 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map
{
"name": "@looker/embed-sdk",
"version": "1.7.1-beta",
"version": "1.8.0",
"description": "A toolkit for embedding Looker",

@@ -23,3 +23,3 @@ "main": "lib/index.js",

"clean": "rm -rf lib dist",
"docs": "typedoc --mode file --out docs",
"docs": "typedoc --gitRevision master --githubPages false --out docs src/index.ts",
"lint": "eslint --format stylish '**/*.ts'",

@@ -31,2 +31,5 @@ "lint-fix": "eslint --format stylish --fix '**/*.ts'",

"python": "webpack --config webpack-devserver.config.js && pip install -r demo/requirements.txt && python demo/demo.py",
"server-prep": "npm run build && webpack --config webpack-devserver.config.js && rm -rf ./server/public && mkdir ./server/public && cp ./demo/*.css ./server/public && cp ./demo/*.html ./server/public && cp ./demo/*.js ./server/public",
"server": "npm run server-prep && cd server && ts-node ./app.ts",
"server-dev": "cd server && find . -type f -name '*.js' -delete && ts-node-dev --watch ./utils ./app.ts",
"test": "npm run lint && karma start karma.conf.js",

@@ -49,14 +52,24 @@ "test-once": "npm run lint && karma start karma.conf.js --single-run "

"@looker/eslint-plugin": "^1.0.0",
"@looker/sdk": "^22.16.0",
"@looker/sdk-node": "^22.16.0",
"@looker/sdk-rtl": "^21.4.0",
"@types/cookie-session": "^2.0.44",
"@types/create-hmac": "^1.1.0",
"@types/express": "^4.17.14",
"@types/jasmine": "^2.8.2",
"@types/node": "^11.12.1",
"@types/readable-stream": "^2.3.14",
"@types/request": "^2.48.8",
"@types/request-promise-native": "^1.0.18",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/typescript-estree": "^5.9.1",
"babel-loader": "^8.2.3",
"body-parser": "^1.20.1",
"cookie-session": "^2.0.0",
"create-hmac": "^1.1.7",
"dotenv": "^8.2.0",
"eslint": "^8.13.0",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-testing-library": "^5.0.3",
"@types/create-hmac": "^1.1.0",
"@types/jasmine": "^2.8.2",
"@types/node": "^11.12.1",
"@types/node-fetch": "^2.6.2",
"create-hmac": "^1.1.7",
"dotenv": "^6.2.0",
"express": "^4.18.2",
"jasmine-core": "^4.0.0",

@@ -68,6 +81,7 @@ "karma": "^6.3.11",

"karma-typescript-es6-transform": "^5.5.3",
"node-fetch": "^2.6.7",
"pre-commit": "^1.2.2",
"prettier": "^2.4.1",
"ts-loader": "^9.2.6",
"ts-node": "^10.9.1",
"ts-node-dev": "^2.0.0",
"typedoc": "^0.22.10",

@@ -74,0 +88,0 @@ "typescript": "^4.5.4",

@@ -5,4 +5,6 @@ # Looker JavaScript Embed SDK

The Looker JavaScript Embed SDK is designed to facilitate using Looker embedded content in your web application. The goal is to make communication between a host website and one or more embedded dashboards, looks or explores easier and more reliable.
The Looker JavaScript Embed SDK is designed to facilitate using Looker embedded content in your web application. The goal is to make communication between a host website and one or more embedded dashboards, looks, explores and extensions easier and more reliable.
The Looker JavaScript Embed SDK typically uses embed SSO to sign an embed url in order to authenticate the user of the embed. This mechanism relies on Looker cookies being available to the embedded IFRAME in order for the application to work. Looker also provides a mechanism that allows embedded Looker IFRAMES to work without the need for cookies. Details can be found [here](#cookieless). Embed SDK functionality that will not work with cookieless embed is identified in this document.
A typical setup might look like this. In this case, a dashboard with an id of `11` is created inside a DOM element with the id `dashboard`. The `dashboard:run:start` and `dashboard:run:complete` events are used to update the state of the embedding window's UI, and a button with an id of `run` is scripted to send a `dashboard:run` message to the dashboard.

@@ -21,8 +23,4 @@

.appendTo('#dashboard')
.on('dashboard:run:start',
() => updateState('#dashboard-state', 'Running')
)
.on('dashboard:run:complete',
() => updateState('#dashboard-state', 'Done')
)
.on('dashboard:run:start', () => updateState('#dashboard-state', 'Running'))
.on('dashboard:run:complete', () => updateState('#dashboard-state', 'Done'))
.build()

@@ -44,3 +42,3 @@ .connect()

First initialize the SDK with address of your Looker server and the endpoint on your server that will perform authentication. (Note: Port must be included if it is required to reach the Looker server from browser clients, e.g. looker.example.com:1919, but the protocol (http/https) should *not* be included.)
First initialize the SDK with address of your Looker server and the endpoint on your server that will perform authentication. (Note: Port must be included if it is required to reach the Looker server from browser clients, e.g. looker.example.com:1919, but the protocol (http/https) should _not_ be included.)

@@ -84,3 +82,2 @@ ```javascript

If you want to send and receive messages to the embedded element you need to call `connect()` which returns a Promise that resolves to the communication interface of the given element:

@@ -96,6 +93,9 @@

This section does not apply to cookieless embed as building URLs in this manner is not supported. See the [cookieless embed](#cookieless) section for details.
The main documentation for Looker SSO embed URLs is [here](https://docs.looker.com/r/sdk/sso-embed). The only difference when creating URLs for the SDK is that you will need to add an `sdk=2` parameter to the Embed URL alongside other parameters like filters and the `embed_domain` parameter. This parameter allows Looker to identify that the SDK is present and can take advantage of additional features provided by the SDK.
```html
/embed/looks/4?embed_domain=https://mywebsite.com => /embed/looks/4?embed_domain=https://mywebsite.com&sdk=2
/embed/looks/4?embed_domain=https://mywebsite.com =>
/embed/looks/4?embed_domain=https://mywebsite.com&sdk=2
```

@@ -107,17 +107,22 @@

This section does not apply to cookieless embed as an alternate mechanism for authentication is used. See the [cookieless embed](#cookieless) section for details.
In order to use the embed SDK on the frontend you must supply a backend service that handles authentication. This service is called by the SDK to generate a signed iframe URL that is unique to the requesting user. The backend process can either generate the signed embed URL itself using an embed secret or the backend process can generate the URL by calling the Looker API. Manual URL generation and signing avoids calling the Looker API resulting in decreased latency. Calling the Looker API requires less code and can be easier to maintain.
### Backend Process
The *backend* process entails hosting a service at an endpoint such as `/auth` which does the following:
1. The backend service initializes the [Looker API SDK](https://docs.looker.com/reference/api-and-integration/api-sdk) based on a client API key and secret typically stored in `Looker.ini` file.
This section does not apply to cookieless embed but a backend process is still required. See the [cookieless embed](#cookieless) section for details.
The _backend_ process entails hosting a service at an endpoint such as `/auth` which does the following:
1. The backend service initializes the [Looker API SDK](https://cloud.google.com/looker/docs/api-sdk) based on a client API key and secret typically stored in `Looker.ini` file.
2. The Embed SDK calls the backend service and provides a query string containing the desired embedding.
3. The backend service takes the information from the Embed SDK *along with any information about the currently authenticated user* and genereates the signed URL. For example, this Python code represents a partial example of a backend that generates the signed URL by calling the Looker API:
3. The backend service takes the information from the Embed SDK _along with any information about the currently authenticated user_ and generates the signed URL. For example, this Python code represents a partial example of a backend that generates the signed URL by calling the Looker API:
```python
# receives a request path that includes /looker_auth
# receives a request path that includes /looker_auth
# as well as the target URL in a query string
req_parts = urlparse(request_path)
req_parts = urlparse(request_path)
req_query = parse_qs(req_parts.query)

@@ -127,3 +132,3 @@ embed_url = req_query['src'][0]

target_sso_url = looker_sdk.models.EmbedSsoParams(target_url, ...) # ... corresponds to very important user attributes
sso_url = looker_api_sdk.create_sso_embed_url(body = target_sso_url) # this is the signed embed URL that is returned
sso_url = looker_api_sdk.create_sso_embed_url(body = target_sso_url) # this is the signed embed URL that is returned
```

@@ -133,4 +138,6 @@

The *frontend* process using the Embed SDK entails:
This section does not apply to cookieless embed but frontend initialization is still required. See the [cookieless embed](#cookieless) section for details.
The _frontend_ process using the Embed SDK entails:
1. The embed SDK is initialized with the Looker host and the backend service:

@@ -145,4 +152,3 @@

```javascript
LookerEmbedSDK.createcreateDashboardWithId(11)
.build()
LookerEmbedSDK.createDashboardWithId(11).build()
// results in a request that includes a query string with:

@@ -156,16 +162,19 @@ // /embed/dashboards/11?sdk=2&embed_deomain=https://yourhost.example.com&...

The Auth endpoint can be configured further, allowing custom Request Headers, as well as CORS support by passing an options object to the `init` method
This section does not apply to cookieless embed as an alternate mechanism for authentication is used. See the [cookieless embed](#cookieless) section for details.
The Auth endpoint can be configured further, allowing custom Request Headers, as well as CORS support by passing an options object to the `init` method
```javascript
LookerEmbedSDK.init('looker.example.com',
{
url: 'https://api.acme.com/looker/auth',
headers: [{'name': 'Foo Header', 'value': 'Foo'}],
params: [{'name': 'foo', 'value': 'bar'}],
withCredentials: true // Needed for CORS requests to Auth endpoint include Http Only cookie headers
})
```
LookerEmbedSDK.init('looker.example.com', {
url: 'https://api.acme.com/looker/auth',
headers: [{ name: 'Foo Header', value: 'Foo' }],
params: [{ name: 'foo', value: 'bar' }],
withCredentials: true, // Needed for CORS requests to Auth endpoint include Http Only cookie headers
})
```
### Node helper
This section does not apply to cookieless embed as an alternate mechanism for authentication is used. See the [cookieless embed](#cookieless) section for details.
If you prefer, your backend service can [implement the signature function](https://github.com/looker/looker_embed_sso_examples) instead of calling the Looker API by using a [Looker Embed secret](https://docs.looker.com/r/sdk/sso-embed). Manually generating the signed URL avoids a call to the Looker API but is more error prone.

@@ -179,11 +188,11 @@

app.get('/looker_auth', function(req, res) {
app.get('/looker_auth', function (req, res) {
// Authenticate the request is from a valid user here
const src = req.query.src;
const src = req.query.src
const host = 'looker.example.com'
const secret = YOUR_EMBED_SECRET
const user = authenticatedUser
const url = createSignedUrl(src, user, host, secret);
res.json({ url });
});
const url = createSignedUrl(src, user, host, secret)
res.json({ url })
})
```

@@ -199,3 +208,3 @@

session_length: number
force_logout_login?: boolean,
force_logout_login?: boolean
permissions: LookerUserPermission[]

@@ -205,7 +214,219 @@ models: string[]

external_group_id?: string
user_attributes?: {[key: string]: any}
access_filters: {[key: string]: any}
user_attributes?: { [key: string]: any }
access_filters: { [key: string]: any }
}
```
<a name='cookieless' id='cookieless'></a>
## Cookieless Embed
Note that cookieless embed does not yet support the use of `withUrl`. An attempt to use this functionality will result in an error being thrown.
Looker cookieless embed allows the Looker application to be embedded by an html page that is served from a different domain than the Looker host. With SSO embed, to avoid third party cookie blocking, the Looker application must be served from a sub domain of the hosting application OR the user must enable third party cookies in the browser. Enabling cookieless embedding is documented in more detail [here](https://cloud.google.com/looker/docs/r/sdk/cookieless-embed). Cookieless embed is available with Looker version 22.20 and above.
Cookieless embed works by using short lived tokens that are kept in the browser and are used to reference the actual session in the Looker server. The Looker UI keeps track of the tokens, and before they expire, requests that the hosting application generate new ones. To this end, the host application is required to implement functionality in the client and in the server.
This functionality will:
- Acquire a new session either by creating or attaching to an existing session associated with the browser (this allows the user to create new IFRAMEs and use the same session).
- Generate new tokens.
### Acquire session backend process
This process will be called every time a Looker embed IFRAME is created. The acquire session backend process requires that the Looker api endpoint `acquire_embed_cookieless_session` be called to create an embed session or attach to an existing embed session. This endpoint is responsible for creating the embed user. This is different from embed SSO whereby the embed login creates the embed user. One major difference in the payloads is that `force_logout_login` is ignored by `acquire_embed_cookieless_session`. Cookieless embed logins ALWAYS force logout login (as there should be no Looker cookies this should be a noop). It should also be noted that this endpoint will NOT update the embed user in Looker if it already exists. There are other endpoints in Looker that can do this.
Cookieless embed sessions are associated with the user's browser user agent. It is important that that user agent for the browser be set on the request.
If successful, the `acquire_embed_cookieless_session` returns a number of tokens:
- `session_reference_token` - this token is used to generate new tokens and created new IFRAMEs. It is important to secure and keep track of this token. It should not be returned to the browser. This token lives for the duration of the session. A new cookieless embed session will need to be created when the `session_reference_token` expires.
- `authentication_token` - this is one time token that has a lifespan of 30 seconds. It is used with the `/login/embed/{target}` endpoint.
- `navigation_token` - this token is used to navigate to different Looker pages in the Looker application. This token lives for 10 minutes.
- `api_token` - this token is used for api calls. This token lives for 10 minutes.
A time to live for each token is also returned. It is important that the response of the `acquire_embed_cookieless_session` be returned to the browser with the exception of the `session_reference_token`. The hosting application MUST keep track of the `session_reference_token` for each user.
The example shown below is simplistic and uses an in memory cache to keep track of the `session_reference_token`. In memory caches will not work in clustered environments so use a distributed cache such as `redis` in production. An alternative is to save the `session_reference_token` in an encrypted session cookie. The use of session cookies is demonstrated [here](/server_utils/routes.ts).
```javascript
// Simple endpoint to acquire an embed session. In this case the user data
// comes from a configuration file. In a real life application the user data
// would be derived from the embedding hosts session.
app.get('/acquire-embed-session', async function (req, res) {
try {
const tokens = await acquireEmbedSession(req.headers['user-agent'], user)
res.json(tokens)
} catch (err) {
res.status(400).send({ message: err.message })
}
})
// The Looker session. In a real application this should not be a global variable,
let lookerSession
// A very simple cache for storing embed sessions. In a real life application the
// embed session should be associated with the embedding application user's session.
const embedSessions = {}
// Simple function to acquire a looker session and then acquire an embed
// session.
async function acquireEmbedSession(userAgent, user) {
await acquireLookerSession()
return acquireEmbedSessionInternal(userAgent, user)
}
// Simple function to acquire a Looker API session.
const acquireLookerSession = async () => {
if (!lookerSession || !lookerSession.activeToken.isActive()) {
const { api_url, client_id, client_secret, verify_ssl } = config
try {
const lookerSettings = DefaultSettings()
lookerSettings.readConfig = () => {
return {
client_id,
client_secret,
}
}
lookerSettings.base_url = api_url
lookerSettings.verify_ssl = verify_ssl
lookerSession = new NodeSession(lookerSettings)
lookerSession.login()
} catch (error) {
console.error('login failed', { error })
throw error
}
}
}
// Simple function to acquire the embed session.
// Note as an additional layer of security the user agent of users
// browser is associated with the embed session. It is important
// that this is available when the embed session is created.
const acquireEmbedSessionInternal = async (userAgent, user) => {
try {
const cacheKey = `${user.external_user_id}/${userAgent}`
const embedSession = embedSessions[cacheKey]
const request = {
...user,
session_reference_token: embedSession?.session_reference_token,
}
const sdk = new Looker40SDK(lookerSession)
const response = await sdk.ok(
sdk.acquire_embed_cookieless_session(request, {
headers: {
'User-Agent': userAgent,
},
})
)
// Note the cachekey includes the embed user id and user agent.
// This allows the embed user to use different browsers at the
// same time. Note that a cache is not the only way to save the
// embed session information, the hosting applications user session
// can also be used (and probably should be).
embedSessions[cacheKey] = response
const {
authentication_token,
authentication_token_ttl,
navigation_token,
navigation_token_ttl,
session_reference_token_ttl,
api_token,
api_token_ttl,
} = response
// Important. Do not return the entire response to the client! The response
// contains the session_reference_token. This token MUST be kept secure.
return {
api_token,
api_token_ttl,
authentication_token,
authentication_token_ttl,
navigation_token,
navigation_token_ttl,
session_reference_token_ttl,
}
} catch (error) {
console.error('embed session acquire failed', { error })
throw error
}
}
```
### Generate tokens backend process
This process is called whenever tokens are about to expire and can be called after a token has expired (for example, a user waking up computer that has gone to sleep). The generate tokens backend process requires that the Looker api endpoint `generate_tokens_for_cookieless_session` be called to generate new navigation and api tokens.
Cookieless embed sessions are associated with the user's browser user agent. It is important that that user agent for the browser be included in the request.
This is very simplistic implementation for demonstration purposes only. An actual implementation should be a lot more robust. If the embed session has expired,
the `session_reference_token_ttl` value will be set to 0. When this happens, embedded IFRAMEs can no longer be used and are locked from further interaction.
```javascript
app.get('/generate-embed-tokens', async function (req, res) {
try {
const tokens = await generateEmbedTokens(req.headers['user-agent'], user)
res.json(tokens)
} catch (err) {
res.status(400).send({ message: err.message })
}
})
export async function generateEmbedTokens(userAgent, user) {
const cacheKey = `${user.external_user_id}/${userAgent}`
const embedSession = embedSessions[cacheKey]
if (!embedSession) {
console.error(
'embed session generate tokens failed, session not yet acquired'
)
throw new Error(
'embed session generate tokens failed, session not yet acquired'
)
}
await acquireLookerSession()
try {
const { api_token, navigation_token, session_reference_token } =
embedSession
const sdk = new Looker40SDK(lookerSession)
const response = await sdk.ok(
sdk.generate_tokens_for_cookieless_session(
{
api_token,
navigation_token,
session_reference_token: session_reference_token || '',
},
{
headers: {
'User-Agent': userAgent,
},
}
)
)
const cacheKey = `${user.external_user_id}/${userAgent}`
embedSessions[cacheKey] = response
return {
api_token: response.api_token,
api_token_ttl: response.api_token_ttl,
navigation_token: response.navigation_token,
navigation_token_ttl: response.navigation_token_ttl,
session_reference_token_ttl: response.session_reference_token_ttl,
}
} catch (error) {
console.error('embed session generate tokens failed', { error })
throw error
}
}
```
### Initializing the Looker SDK in the frontend
Cookieless embed is initialized by calling `LookerEmbedSDK.initCookieless` passing in the Looker host value and the the urls of the backend endpoints described previously. Once a Looker embed IFRAME is created it will communicate with the Embed SDK running in the host application and use the callbacks appropriately.
```javascript
LookerEmbedSDK.initCookieless(
'looker.example.com',
'/acquire-embed-session',
'/generate-embed-tokens'
)
```
## Demo

@@ -215,27 +436,46 @@

The python simple demo server does not support cookieless embed but alternative TypeScript backend is available which does support cookieless embed.
### Step 1 - Enable Embedding in your Looker instance
(This is documented in more detail [here](https://docs.looker.com/r/sdk/sso-embed))
Enabling SSO embedding is documented in more detail [here](https://cloud.google.com/looker/docs/single-sign-on-embedding).
Enabling cookieless embedding is documented in more detail [here](https://cloud.google.com/looker/docs/r/sdk/cookieless-embed).
* Navigate to Admin > *Platform* Embed on your Looker instance. This requires Admin privileges.
* The demo server runs by default at [http://localhost:8080](http://localhost:8080). By adding that address to "Embedded Domain Whitelist" you can enabled the demo to receive messages from Looker.
* Turn on "Embed Authentication"
* In order to use embedding you must generate an "Embed Secret"
- Navigate to Admin > _Platform_ Embed on your Looker instance. This requires Admin privileges.
- The demo server runs by default at [http://localhost:8080](http://localhost:8080). By adding that address to "Embedded Domain Whitelist" you can enabled the demo to receive messages from Looker.
- Turn on "Embed SSO Authentication"
- In order to use embedding you must generate an "Embed Secret" for SSO embedding and/or a JWT secret for cookieless embedding. Note that a Looker instance can support both types of embedding at the same time.
Additional steps for cookieless embed:
- Navigate to Admin > _Platform_ Embed on your Looker instance. This requires Admin privileges.
- Generate an Embed JWT secret. This is used internally and the hosting application does not need to know what it is.
- Navigate to Admin > _Labs_ Experimental on your Looker instance. This requires Admin privileges.
- Toggle "Cookieless Embed" on. Note that a Looker instance can support SSO and Cookieless embed clients.
### Step 2 - Customize the Demo settings for your Looker instance
* If you are using the main `demo.py`, provide your API credentials to the server by updating `demo/looker.ini` following [these instructions](https://community.looker.com/technical-tips-tricks-1021/the-how-to-on-initializing-the-sdk-with-different-profiles-in-your-ini-file-26846), with credentials obtained from [the Users page](https://docs.looker.com/reference/api-and-integration/api-auth).
Note that `demo.py` and `demo_self_signed.py` have NOT been updated to support cookieless embedding. This section ONLY applies to SSO embedding. The cookieless embed demo currently requires the use of the development server.
* Alternatively, if you are using `demo_self_signed.py`, provide your embed secret to the server. You can do this a couple ways.
* Set it as `LOOKER_EMBED_SECRET` in your shell environment.
* Create a file named `.env` in the root of the sdk directory. Add a line to that file: `LOOKER_EMBED_SECRET="YourLookerSecret"`
- If you are using the main `demo.py`, provide your API credentials to the server by updating `demo/looker.ini` following [these instructions](https://community.looker.com/technical-tips-tricks-1021/the-how-to-on-initializing-the-sdk-with-different-profiles-in-your-ini-file-26846), with credentials obtained from [the Users page](https://cloud.google.com/looker/docs/api-auth).
* Provide your Looker instance host address to the server:
* Create a `.env` file in the main embed-sdk directory and add `LOOKER_EMBED_HOST="yourinstance.looker.com:yourport"`
* **The Looker embed host should not include the protocol!**
- Alternatively, if you are using `demo_self_signed.py`, provide your embed secret to the server. You can do this a couple ways.
* Edit the `demo/demo_config.ts` file to be appropriate for the pages you want to embed.
- Set it as `LOOKER_EMBED_SECRET` in your shell environment.
- Create a file named `.env` in the root of the sdk directory. Add a line to that file: `LOOKER_EMBED_SECRET="YourLookerSecret"`
- Another alternative is to use the TypeScript demo server. The embed secret can be provided in the following way:
- Set it as `LOOKER_EMBED_SECRET` in your shell environment.
- Create a file named `.env` in the root of the sdk directory. Add a line to that file: `LOOKER_EMBED_SECRET="YourLookerSecret"`
- Provide your Looker instance host address to the server:
- Create a `.env` file in the main embed-sdk directory and add `LOOKER_EMBED_HOST="yourinstance.looker.com:yourport"`
- **The Looker embed host should not include the protocol!**
- Edit the `demo/demo_config.ts` file to be appropriate for the pages you want to embed. It is also possible to override the `demo/demo_config.ts` in the `.env` file. See [here](#env) for more details.
```javascript
// The address of your Looker instance. Required.
// The address of your Looker instance. Required.
// Include the port if it is necessary when accessing looker in a browser

@@ -251,3 +491,3 @@ // Do NOT include the protocol

* Edit the `demo/demo_user.json` file to be appropriate for the type of user you want to embed. Normally your backend service would use information about the user logged into your embedding application (e.g your customer portal) to inform Looker about important user properties that control data access controls.
- Edit the `demo/demo_user.json` file to be appropriate for the type of user you want to embed. Normally your backend service would use information about the user logged into your embedding application (e.g your customer portal) to inform Looker about important user properties that control data access controls. Note that the `demo/demo_user.json` file is also used for cookieless embedding. The one difference is that cookieless_embed will ignore the value of `force_logout_login` and will ALWAYs treat the value as `true`.

@@ -307,12 +547,16 @@ ```javascript

Run the following commands from the top-level embed-sdk directory.
The following applies to SSO embed only. Run the following commands from the top-level embed-sdk directory.
* `npm install`
* `npm run python`
* The server will print out what host and port it is running on.
- `npm install`
- `npm run python`
- The server will print out what host and port it is running on.
If you want to use the `demo_self_signed.py` example you will need to update `packages.json` and replace `demo.py` with `demo_self_signed.py`.
## Troubleshooting
Alternatively run the TypeScript demo server which also supports cookieless embed.
- `npm install`
- `npm run server`
- The server will listen on port 8080.
### Logging

@@ -332,1 +576,24 @@

```
### <a name='env' id='env'></a> `.env` setup
The embed demo environment can be configured using a `.env` file. The following is a template that can be used to create the file (in the root of this repo). The `.env` file should never be stored in your git repo and is included in the repo's `.ignore` file.
```shell
LOOKER_EMBED_HOST=mycompany.looker.com
LOOKER_EMBED_API_URL=https://mycompany.looker.com:19999
LOOKER_DEMO_HOST=localhost
LOOKER_DEMO_PORT=8080
LOOKER_EMBED_SECRET=
LOOKER_CLIENT_ID=
LOOKER_CLIENT_SECRET=
LOOKER_DASHBOARD_ID=1
LOOKER_LOOK_ID=1
LOOKER_EXPLORE_ID=thelook::orders
LOOKER_EXTENSION_ID=extension::my-great-extension
COOKIE_SECRET=cookie_stash
```
## Embedded Javascript Events
Prior to the release of the Embed SDK, Looker exposed an API that utilized JavaScript `postMessage` events. This API is still available for customers who cannot or do not want to use the Embed SDK (note that using the Embed SDK is highly recommended as it provides additional functionality and is simpler to use). An example application has been created to ensure that cookieless embed also works with JavaScript `postMessage` events. This example can be found [here](demo/message_example.ts).

@@ -55,2 +55,12 @@ /*

/**
* Convenience method for sending an edit message to the embedded dashboard.
*
* Requires Looker 22.20 and Dashboards Next (see [[EmbedBuilder.withNext]]).
*/
edit() {
this.send('dashboard:edit')
}
/**
* Convenience method for updating the filters of the embedded dashboard.

@@ -57,0 +67,0 @@ *

@@ -33,3 +33,4 @@ /*

LookerEmbedFilterParams,
LookerEmbedCookielessSessionData,
CookielessCallback,
CookielessRequestInit,
} from './types'

@@ -42,7 +43,7 @@

auth?: LookerAuthConfig
acquireSessionCallback?: () => Promise<LookerEmbedCookielessSessionData>
generateTokensCallback?: () => Promise<LookerEmbedCookielessSessionData>
acquireSession?: CookielessCallback | string | CookielessRequestInit
generateTokens?: CookielessCallback | string | CookielessRequestInit
}
interface UrlParams {
export interface UrlParams {
[key: string]: string

@@ -262,2 +263,5 @@ }

withUrl(url: string) {
if (this.isCookielessEmbed) {
throw new Error('withUrl not supported by cookieless embed')
}
this._url = url

@@ -332,17 +336,17 @@ return this

get isCookielessEmbed() {
return !!this._hostSettings.acquireSessionCallback
return !!this._hostSettings.acquireSession
}
/**
* Cookieless embed session prepare callback
* Cookieless embed acquire session
*/
get acquireSessionCallback() {
return this._hostSettings.acquireSessionCallback
get acquireSession() {
return this._hostSettings.acquireSession
}
/**
* Cookieless embed refresh api token callback
* Cookieless embed generate tokens
*/
get generateTokensCallback() {
return this._hostSettings.generateTokensCallback
get generateTokens() {
return this._hostSettings.generateTokens
}

@@ -349,0 +353,0 @@

@@ -31,2 +31,6 @@ /*

import type { EmbedBuilder } from './embed_builder'
import type {
CookielessRequestInit,
LookerEmbedCookielessSessionData,
} from './types'

@@ -41,2 +45,5 @@ const IS_URL = /^https?:\/\//

export class EmbedClient<T> {
private static sessionAcquired = false
private static acquireSessionPromise?: Promise<string>
_hostBuilder: ChattyHostBuilder | null = null

@@ -51,2 +58,3 @@ _host: ChattyHost | null = null

_cookielessNavigationTokenTtl?: number | null
_cookielessSessionReferenceTokenTtl?: number | null

@@ -92,3 +100,3 @@ /**

this._cookielessApiToken &&
this._builder.generateTokensCallback
this._builder.generateTokens
) {

@@ -101,3 +109,4 @@ if (this._cookielessInitialized) {

navigation_token_ttl,
} = await this._builder.generateTokensCallback()
session_reference_token_ttl,
} = await this.generateTokens()
this._cookielessApiToken = api_token

@@ -107,2 +116,4 @@ this._cookielessApiTokenTtl = api_token_ttl

this._cookielessNavigationTokenTtl = navigation_token_ttl
this._cookielessSessionReferenceTokenTtl =
session_reference_token_ttl
} else {

@@ -117,2 +128,4 @@ this._cookielessInitialized = true

navigation_token_ttl: this._cookielessNavigationTokenTtl,
session_reference_token_ttl:
this._cookielessSessionReferenceTokenTtl,
})

@@ -192,16 +205,14 @@ }

private sessionAcquired = false
private acquireSessionPromise?: Promise<string>
private async acquireCookielessEmbedSession(): Promise<string> {
if (this.sessionAcquired) {
if (EmbedClient.sessionAcquired) {
return this.acquireCookielessEmbedSessionInternal()
}
if (this.acquireSessionPromise) {
await this.acquireSessionPromise
if (EmbedClient.acquireSessionPromise) {
await EmbedClient.acquireSessionPromise
return this.acquireCookielessEmbedSessionInternal()
}
this.acquireSessionPromise = this.acquireCookielessEmbedSessionInternal()
return this.acquireSessionPromise.then((url) => {
this.sessionAcquired = true
EmbedClient.acquireSessionPromise =
this.acquireCookielessEmbedSessionInternal()
return EmbedClient.acquireSessionPromise.then((url) => {
EmbedClient.sessionAcquired = true
return url

@@ -212,8 +223,8 @@ })

private async acquireCookielessEmbedSessionInternal(): Promise<string> {
const { acquireSessionCallback, generateTokensCallback } = this._builder
if (!acquireSessionCallback) {
throw new Error('invalid state: acquireSessionCallback not defined')
const { acquireSession, generateTokens } = this._builder
if (!acquireSession) {
throw new Error('invalid state: acquireSession not defined')
}
if (!generateTokensCallback) {
throw new Error('invalid state: generateTokensCallback not defined')
if (!generateTokens) {
throw new Error('invalid state: generateTokens not defined')
}

@@ -226,3 +237,4 @@ const {

navigation_token_ttl,
} = await acquireSessionCallback()
session_reference_token_ttl,
} = await this.acquireSession()
if (!authentication_token || !navigation_token || !api_token) {

@@ -235,2 +247,3 @@ throw new Error('failed to prepare cookieless embed session')

this._cookielessNavigationTokenTtl = navigation_token_ttl
this._cookielessSessionReferenceTokenTtl = session_reference_token_ttl
const apiHost = `https://${this._builder.apiHost}`

@@ -247,2 +260,66 @@ const sep =

private async acquireSession(): Promise<LookerEmbedCookielessSessionData> {
const { acquireSession } = this._builder
if (typeof acquireSession === 'function') {
return await acquireSession()
}
try {
const { url, init } = this.getResource(acquireSession!)
const resp = await fetch(url, init)
if (!resp.ok) {
console.error('acquire embed session failed', { resp })
throw new Error(`acquire embed session failed`)
}
return (await resp.json()) as LookerEmbedCookielessSessionData
} catch (error: any) {
console.error(error)
throw new Error(`acquire embed session failed`)
}
}
private async generateTokens(): Promise<LookerEmbedCookielessSessionData> {
const { generateTokens } = this._builder
if (typeof generateTokens === 'function') {
return await generateTokens()
}
try {
const { url, init: defaultInit } = this.getResource(generateTokens!)
const init = defaultInit || {
body: JSON.stringify({
api_token: this._cookielessApiToken,
navigation_token: this._cookielessNavigationToken,
}),
headers: {
'content-type': 'application/json',
},
method: 'PUT',
}
const resp = await fetch(url, init)
if (!resp.ok) {
if (resp.status === 400) {
return { session_reference_token_ttl: 0 }
}
console.error('generate tokens failed', { resp })
throw new Error(`generate tokens failed`)
}
return (await resp.json()) as LookerEmbedCookielessSessionData
} catch (error: any) {
console.error(error)
throw new Error(`generate tokens failed`)
}
}
private getResource(resource: string | CookielessRequestInit) {
let url
let init
if (typeof resource === 'object') {
const { url: tempUrl, ...rest } = resource
init = rest
url = tempUrl
} else {
url = resource
}
return { init, url }
}
/**

@@ -257,2 +334,5 @@ * Establish two way communication with embedded content. Returns a promise that resolves to a

if (this._builder.url) {
if (this._builder.isCookielessEmbed) {
throw new Error('withUrl not supported by cookieless embed')
}
this._connection = this.createIframe(this._builder.url)

@@ -259,0 +339,0 @@ } else {

@@ -34,3 +34,4 @@ /*

LookerAuthConfig,
LookerEmbedCookielessSessionData,
CookielessCallback,
CookielessRequestInit,
} from './types'

@@ -42,2 +43,5 @@

export type { LookerEmbedLook } from './look_client'
export type { LookerEmbedBase } from './embed_base'
export type { EmbedBuilder, UrlParams } from './embed_builder'
export type { EmbedClient } from './embed'
export * from './types'

@@ -57,2 +61,4 @@

this.auth = typeof auth === 'string' ? { url: auth } : auth
this.acquireSession = undefined
this.generateTokens = undefined
}

@@ -63,22 +69,23 @@

*
* @param apiHost The address or base URL of the Looker host (example.looker.com:9999, https://example.looker.com:9999)
* This is required for verification of messages sent from the embedded content.
* @param acquireSessionCallback A callback that will acquire a cookieless session. The `acquire_embed_cookieless_session`
* api end point should ultimately be called. The recommended approach is via a proxy endpoint provided by the hosting
* application. Two tokens are returned. The navigation token is automatically appended to Looker URLs that result in
* navigation in the embedded IFRAME. The api token is sent to the Looker Application running in the embedded IFRAME
* once the underlying chatty connection has been established.
* @param generateTokensCallback A callback that will generate new navigation and api tokens. The `generate_tokens_for_cookieless_session`
* api end point should ultimately be called. The recommended approach is via a proxy endpoint provided by the hosting
* application. The Embed SDK will call this prior to the api and navigation tokens expiring and will send the new api
* token to the embedded IFRAME.
* @param apiHost The address or base URL of the host (example.looker.com:9999, https://example.looker.com:9999)
* @param acquireSession is either a string containing a server endpoint that will acquire the embed session OR
* a RequestInfo object for a fetch call to the server endpoint that will acquire the embed session OR
* a callback that will invoke the server endpoint that will acquire the embed session.
* The server endpoint must ultimately call the Looker endpoint `acquire_embed_cookieless_session`.
* @param generateTokens is either a string containing a server endpoint that will generate new tokens OR
* a RequestInfo object for a fetch call to the server endpoint that will generate new tokens OR
* a callback that will invoke the server endpoint that will generate new tokens.
* The server endpoint should ultimately call the Looker endpoint `generate_tokens_for_cookieless_session`.
*
* Looker 22.20+
*/
static initCookieless(
apiHost: string,
acquireSessionCallback: () => Promise<LookerEmbedCookielessSessionData>,
generateTokensCallback: () => Promise<LookerEmbedCookielessSessionData>
acquireSession: string | CookielessRequestInit | CookielessCallback,
generateTokens: string | CookielessRequestInit | CookielessCallback
) {
this.apiHost = apiHost
this.acquireSessionCallback = acquireSessionCallback
this.generateTokensCallback = generateTokensCallback
this.acquireSession = acquireSession
this.generateTokens = generateTokens
this.auth = undefined
}

@@ -223,3 +230,3 @@

static acquireSessionCallback?: () => Promise<LookerEmbedCookielessSessionData>
static acquireSession?: string | CookielessRequestInit | CookielessCallback

@@ -230,3 +237,3 @@ /**

static generateTokensCallback?: () => Promise<LookerEmbedCookielessSessionData>
static generateTokens?: string | CookielessRequestInit | CookielessCallback
}

@@ -42,3 +42,19 @@ /*

/**
* Cookieless request init
* Looker 22.20+
*/
export interface CookielessRequestInit extends RequestInit {
url: string
}
/**
* Cookieless request callback function
* Looker 22.20+
*/
export type CookielessCallback = () => Promise<LookerEmbedCookielessSessionData>
/**
* Cookieless session data
* Looker 23.0+
*/

@@ -73,3 +89,3 @@ export interface LookerEmbedCookielessSessionData {

*/
session_ttl?: number | null
session_reference_token_ttl?: number | null
}

@@ -91,3 +107,3 @@

interface DashboardLayout {
export interface DashboardLayout {
id: string

@@ -109,3 +125,3 @@ dashboard_id: string

interface DashboardLayoutComponent {
export interface DashboardLayoutComponent {
id: string

@@ -175,2 +191,38 @@ dashboard_layout_id: string

/**
* Cookieless embed session token request
* Looker 22.20+
*/
export type SessionTokenRequest = EventDetail
/**
* Cookieless session status event
* Looker 23.0+
*/
export interface SessionStatus extends EventDetail {
/**
* Session time to live in seconds
*/
session_ttl: number
/**
* Session expired when true
*/
expired: boolean
/**
* Session interrupted when true. This means new
* tokens could not be retrieved in a timely manner.
* Can happen if server is temporarily unavailable
* for some reason
*/
interrupted: boolean
/**
* Interrupted session can be recovered. When false
* session cannot continue. This is most likely
* a problem with the embedding application.
*/
recoverable?: boolean
}
/**
* Detailed dashboard data returned by dashboard events

@@ -182,2 +234,3 @@ */

title: string
canEdit: boolean
dashboard_filters: LookerEmbedFilterParams

@@ -341,3 +394,3 @@ absoluteUrl: string

* Look save event details
* Looker version 21.6
* Looker version 21.6+
*/

@@ -348,3 +401,3 @@

* Folder Look is associated with
* Looker version 21.8
* Looker version 21.8+
*/

@@ -356,3 +409,3 @@ spaceId: number

* Look save event
* Looker version 21.6
* Looker version 21.6+
*/

@@ -432,5 +485,25 @@ export interface LookSaveEvent extends LookerEmbedEvent {

/**
* Dashboard saved event
* Looker 21.6
* Dashboard editing started event.
* Not available to legacy dashboards.
* Looker 22.20+
*/
'dashboard:edit:start': (
this: LookerEmbedDashboard,
event: DashboardEvent
) => void
/**
* Dashboard editing cancelled event.
* Not available to legacy dashboards.
* Looker 22.20+
*/
'dashboard:edit:cancel': (
this: LookerEmbedDashboard,
event: DashboardEvent
) => void
/**
* Dashboard saved event. Fired when a dashboard
* being edited is saved. Use in conjunction with
* `dashboard:edit:start` and `dashboard:edit:save`.
* Looker 21.6+
*/
'dashboard:save:complete': (

@@ -442,3 +515,3 @@ this: LookerEmbedDashboard,

* Dashboard deleted event
* Looker 21.6
* Looker 21.6+
*/

@@ -488,3 +561,3 @@ 'dashboard:delete:complete': (

* Look saved event
* Looker 21.6
* Looker 21.6+
*/

@@ -494,3 +567,3 @@ 'look:save:complete': (this: LookerEmbedLook, event: LookSaveEvent) => void

* Look deleted event
* Looker 21.6
* Looker 21.6+
*/

@@ -506,4 +579,17 @@ 'look:delete:complete': (this: LookerEmbedLook, event: LookSaveEvent) => void

) => void
/**
* Cookieless embed session tokens request event
* Looker 22.20+
*/
'session:token:request': (
this: LookerEmbedBase,
event: SessionTokenRequest
) => void
/**
* Cookieless embed session status event
* Looker 23.0+
*/
'session:status': (this: LookerEmbedBase, event: SessionStatus) => void
[key: string]: any
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc