@thatopen/services 0.16.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -7801,12 +7801,16 @@ return main;`);
7801
7801
  * Creates a hidden file attached to a parent item (e.g., dependencies, assets).
7802
7802
  * @param file - The file to upload.
7803
7803
  * @param parentFileId - The parent item's unique identifier.
7804
+ * @param tag - Optional label to tell hidden files of the same parent apart;
7805
+ * filter on it with {@link getHiddenFilesByParent}. Up to 50 characters:
7806
+ * letters, digits and `:._-`, starting with a letter or digit.
7804
7807
  * @returns The hidden file ID.
7805
7808
  */
7806
- async createHiddenFile(file, parentFileId) {
7809
+ async createHiddenFile(file, parentFileId, tag) {
7807
7810
  const formData = new FormData();
7808
7811
  formData.append("file", file);
7809
7812
  formData.append("parentItemId", parentFileId);
7813
+ if (tag != null) formData.append("tag", tag);
7810
7814
  return await this.#requestApi(
7811
7815
  "POST",
7812
7816
  `${ITEM_PATH}/${HIDDEN_PATH}`,
@@ -7821,14 +7825,17 @@ return main;`);
7821
7825
  * (e.g. 3D Tiles); upload in chunks of up to 100 files per call.
7822
7826
  * @param files - The files to upload.
7823
7827
  * @param parentFileId - The parent item's unique identifier.
7828
+ * @param tag - Optional label, as in {@link createHiddenFile}. One tag
7829
+ * applies to every file in the batch.
7824
7830
  * @returns One result per uploaded file, in order, each with its hidden file ID.
7825
7831
  */
7826
- async createHiddenFilesBatch(files, parentFileId) {
7832
+ async createHiddenFilesBatch(files, parentFileId, tag) {
7827
7833
  const formData = new FormData();
7828
7834
  for (const file of files) {
7829
7835
  formData.append("files", file);
7830
7836
  }
7831
7837
  formData.append("parentItemId", parentFileId);
7838
+ if (tag != null) formData.append("tag", tag);
7832
7839
  return await this.#requestApi(
7833
7840
  "POST",
7834
7841
  `${ITEM_PATH}/${HIDDEN_PATH}/batch`,
@@ -7925,14 +7932,17 @@ return main;`);
7925
7932
  );
7926
7933
  }
7927
7934
  /**
7928
- * Lists all hidden files attached to a parent item.
7935
+ * Lists the hidden files attached to a parent item.
7929
7936
  * @param parentFileId - The parent item's unique identifier.
7937
+ * @param tag - Optional filter: only hidden files uploaded with this tag. A
7938
+ * tagged listing comes back in creation order.
7930
7939
  * @returns Array of hidden file entities.
7931
7940
  */
7932
- async getHiddenFilesByParent(parentFileId) {
7941
+ async getHiddenFilesByParent(parentFileId, tag) {
7933
7942
  return await this.#requestApi(
7934
7943
  "GET",
7935
- `${ITEM_PATH}/${parentFileId}/${HIDDEN_PATH}`
7944
+ `${ITEM_PATH}/${parentFileId}/${HIDDEN_PATH}`,
7945
+ { ...tag != null && { query: { tag } } }
7936
7946
  );
7937
7947
  }
7938
7948
  /**
@@ -629,18 +629,23 @@ export declare class EngineServicesClient {
629
629
  * Creates a hidden file attached to a parent item (e.g., dependencies, assets).
630
630
  * @param file - The file to upload.
631
631
  * @param parentFileId - The parent item's unique identifier.
632
+ * @param tag - Optional label to tell hidden files of the same parent apart;
633
+ * filter on it with {@link getHiddenFilesByParent}. Up to 50 characters:
634
+ * letters, digits and `:._-`, starting with a letter or digit.
632
635
  * @returns The hidden file ID.
633
636
  */
634
- createHiddenFile(file: File | Blob, parentFileId: string): Promise<CreateHiddenItemResult>;
637
+ createHiddenFile(file: File | Blob, parentFileId: string, tag?: string): Promise<CreateHiddenItemResult>;
635
638
  /**
636
639
  * Creates many hidden files attached to a parent item in a single request.
637
640
  * Use this instead of many `createHiddenFile` calls when uploading large sets
638
641
  * (e.g. 3D Tiles); upload in chunks of up to 100 files per call.
639
642
  * @param files - The files to upload.
640
643
  * @param parentFileId - The parent item's unique identifier.
644
+ * @param tag - Optional label, as in {@link createHiddenFile}. One tag
645
+ * applies to every file in the batch.
641
646
  * @returns One result per uploaded file, in order, each with its hidden file ID.
642
647
  */
643
- createHiddenFilesBatch(files: (File | Blob)[], parentFileId: string): Promise<CreateHiddenItemsBatchResult>;
648
+ createHiddenFilesBatch(files: (File | Blob)[], parentFileId: string, tag?: string): Promise<CreateHiddenItemsBatchResult>;
644
649
  /**
645
650
  * Deletes a hidden file by its ID.
646
651
  * @param hiddenId - The hidden file's unique identifier.
@@ -697,11 +702,13 @@ export declare class EngineServicesClient {
697
702
  */
698
703
  getHiddenFileSignedUrlsBatch(hiddenIds: string[], expiresIn?: number): Promise<HiddenFileSignedUrlBatchEntry[]>;
699
704
  /**
700
- * Lists all hidden files attached to a parent item.
705
+ * Lists the hidden files attached to a parent item.
701
706
  * @param parentFileId - The parent item's unique identifier.
707
+ * @param tag - Optional filter: only hidden files uploaded with this tag. A
708
+ * tagged listing comes back in creation order.
702
709
  * @returns Array of hidden file entities.
703
710
  */
704
- getHiddenFilesByParent(parentFileId: string): Promise<HiddenFileEntity[]>;
711
+ getHiddenFilesByParent(parentFileId: string, tag?: string): Promise<HiddenFileEntity[]>;
705
712
  /**
706
713
  * Deletes all hidden files attached to a parent item.
707
714
  * @param parentFileId - The parent item's unique identifier.
package/dist/index.cjs.js CHANGED
@@ -1,2 +1,2 @@
1
1
  "use strict";var St=Object.defineProperty;var Xe=n=>{throw TypeError(n)};var Ot=(n,e,t)=>e in n?St(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var E=(n,e,t)=>Ot(n,typeof e!="symbol"?e+"":e,t),_e=(n,e,t)=>e.has(n)||Xe("Cannot "+t);var u=(n,e,t)=>(_e(n,e,"read from private field"),t?t.call(n):e.get(n)),_=(n,e,t)=>e.has(n)?Xe("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(n):e.set(n,t),T=(n,e,t,s)=>(_e(n,e,"write to private field"),s?s.call(n,t):e.set(n,t),t),a=(n,e,t)=>(_e(n,e,"access private method"),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=Object.create(null);P.open="0";P.close="1";P.ping="2";P.pong="3";P.message="4";P.upgrade="5";P.noop="6";const ce=Object.create(null);Object.keys(P).forEach(n=>{ce[P[n]]=n});const Se={type:"error",data:"parser error"},nt=typeof Blob=="function"||typeof Blob<"u"&&Object.prototype.toString.call(Blob)==="[object BlobConstructor]",rt=typeof ArrayBuffer=="function",it=n=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(n):n&&n.buffer instanceof ArrayBuffer,He=({type:n,data:e},t,s)=>nt&&e instanceof Blob?t?s(e):ze(e,s):rt&&(e instanceof ArrayBuffer||it(e))?t?s(e):ze(new Blob([e]),s):s(P[n]+(e||"")),ze=(n,e)=>{const t=new FileReader;return t.onload=function(){const s=t.result.split(",")[1];e("b"+(s||""))},t.readAsDataURL(n)};function Qe(n){return n instanceof Uint8Array?n:n instanceof ArrayBuffer?new Uint8Array(n):new Uint8Array(n.buffer,n.byteOffset,n.byteLength)}let be;function Ct(n,e){if(nt&&n.data instanceof Blob)return n.data.arrayBuffer().then(Qe).then(e);if(rt&&(n.data instanceof ArrayBuffer||it(n.data)))return e(Qe(n.data));He(n,!1,t=>{be||(be=new TextEncoder),e(be.encode(t))})}const Ze="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",ee=typeof Uint8Array>"u"?[]:new Uint8Array(256);for(let n=0;n<Ze.length;n++)ee[Ze.charCodeAt(n)]=n;const Rt=n=>{let e=n.length*.75,t=n.length,s,r=0,i,o,h,f;n[n.length-1]==="="&&(e--,n[n.length-2]==="="&&e--);const m=new ArrayBuffer(e),y=new Uint8Array(m);for(s=0;s<t;s+=4)i=ee[n.charCodeAt(s)],o=ee[n.charCodeAt(s+1)],h=ee[n.charCodeAt(s+2)],f=ee[n.charCodeAt(s+3)],y[r++]=i<<2|o>>4,y[r++]=(o&15)<<4|h>>2,y[r++]=(h&3)<<6|f&63;return m},$t=typeof ArrayBuffer=="function",je=(n,e)=>{if(typeof n!="string")return{type:"message",data:ot(n,e)};const t=n.charAt(0);return t==="b"?{type:"message",data:Nt(n.substring(1),e)}:ce[t]?n.length>1?{type:ce[t],data:n.substring(1)}:{type:ce[t]}:Se},Nt=(n,e)=>{if($t){const t=Rt(n);return ot(t,e)}else return{base64:!0,data:n}},ot=(n,e)=>{switch(e){case"blob":return n instanceof Blob?n:new Blob([n]);case"arraybuffer":default:return n instanceof ArrayBuffer?n:n.buffer}},at="",Pt=(n,e)=>{const t=n.length,s=new Array(t);let r=0;n.forEach((i,o)=>{He(i,!1,h=>{s[o]=h,++r===t&&e(s.join(at))})})},Bt=(n,e)=>{const t=n.split(at),s=[];for(let r=0;r<t.length;r++){const i=je(t[r],e);if(s.push(i),i.type==="error")break}return s};function xt(){return new TransformStream({transform(n,e){Ct(n,t=>{const s=t.length;let r;if(s<126)r=new Uint8Array(1),new DataView(r.buffer).setUint8(0,s);else if(s<65536){r=new Uint8Array(3);const i=new DataView(r.buffer);i.setUint8(0,126),i.setUint16(1,s)}else{r=new Uint8Array(9);const i=new DataView(r.buffer);i.setUint8(0,127),i.setBigUint64(1,BigInt(s))}n.data&&typeof n.data!="string"&&(r[0]|=128),e.enqueue(r),e.enqueue(t)})}})}let Te;function oe(n){return n.reduce((e,t)=>e+t.length,0)}function ae(n,e){if(n[0].length===e)return n.shift();const t=new Uint8Array(e);let s=0;for(let r=0;r<e;r++)t[r]=n[0][s++],s===n[0].length&&(n.shift(),s=0);return n.length&&s<n[0].length&&(n[0]=n[0].slice(s)),t}function It(n,e){Te||(Te=new TextDecoder);const t=[];let s=0,r=-1,i=!1;return new TransformStream({transform(o,h){for(t.push(o);;){if(s===0){if(oe(t)<1)break;const f=ae(t,1);i=(f[0]&128)===128,r=f[0]&127,r<126?s=3:r===126?s=1:s=2}else if(s===1){if(oe(t)<2)break;const f=ae(t,2);r=new DataView(f.buffer,f.byteOffset,f.length).getUint16(0),s=3}else if(s===2){if(oe(t)<8)break;const f=ae(t,8),m=new DataView(f.buffer,f.byteOffset,f.length),y=m.getUint32(0);if(y>Math.pow(2,21)-1){h.enqueue(Se);break}r=y*Math.pow(2,32)+m.getUint32(4),s=3}else{if(oe(t)<r)break;const f=ae(t,r);h.enqueue(je(i?f:Te.decode(f),e)),s=0}if(r===0||r>n){h.enqueue(Se);break}}}})}const ct=4;function w(n){if(n)return Lt(n)}function Lt(n){for(var e in w.prototype)n[e]=w.prototype[e];return n}w.prototype.on=w.prototype.addEventListener=function(n,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+n]=this._callbacks["$"+n]||[]).push(e),this};w.prototype.once=function(n,e){function t(){this.off(n,t),e.apply(this,arguments)}return t.fn=e,this.on(n,t),this};w.prototype.off=w.prototype.removeListener=w.prototype.removeAllListeners=w.prototype.removeEventListener=function(n,e){if(this._callbacks=this._callbacks||{},arguments.length==0)return this._callbacks={},this;var t=this._callbacks["$"+n];if(!t)return this;if(arguments.length==1)return delete this._callbacks["$"+n],this;for(var s,r=0;r<t.length;r++)if(s=t[r],s===e||s.fn===e){t.splice(r,1);break}return t.length===0&&delete this._callbacks["$"+n],this};w.prototype.emit=function(n){this._callbacks=this._callbacks||{};for(var e=new Array(arguments.length-1),t=this._callbacks["$"+n],s=1;s<arguments.length;s++)e[s-1]=arguments[s];if(t){t=t.slice(0);for(var s=0,r=t.length;s<r;++s)t[s].apply(this,e)}return this};w.prototype.emitReserved=w.prototype.emit;w.prototype.listeners=function(n){return this._callbacks=this._callbacks||{},this._callbacks["$"+n]||[]};w.prototype.hasListeners=function(n){return!!this.listeners(n).length};const me=typeof Promise=="function"&&typeof Promise.resolve=="function"?e=>Promise.resolve().then(e):(e,t)=>t(e,0),S=typeof self<"u"?self:typeof window<"u"?window:Function("return this")(),qt="arraybuffer";function ht(n,...e){return e.reduce((t,s)=>(n.hasOwnProperty(s)&&(t[s]=n[s]),t),{})}const Ut=S.setTimeout,Dt=S.clearTimeout;function ge(n,e){e.useNativeTimers?(n.setTimeoutFn=Ut.bind(S),n.clearTimeoutFn=Dt.bind(S)):(n.setTimeoutFn=S.setTimeout.bind(S),n.clearTimeoutFn=S.clearTimeout.bind(S))}const Ft=1.33;function Mt(n){return typeof n=="string"?Ht(n):Math.ceil((n.byteLength||n.size)*Ft)}function Ht(n){let e=0,t=0;for(let s=0,r=n.length;s<r;s++)e=n.charCodeAt(s),e<128?t+=1:e<2048?t+=2:e<55296||e>=57344?t+=3:(s++,t+=4);return t}function ut(){return Date.now().toString(36).substring(3)+Math.random().toString(36).substring(2,5)}function jt(n){let e="";for(let t in n)n.hasOwnProperty(t)&&(e.length&&(e+="&"),e+=encodeURIComponent(t)+"="+encodeURIComponent(n[t]));return e}function Vt(n){let e={},t=n.split("&");for(let s=0,r=t.length;s<r;s++){let i=t[s].split("=");e[decodeURIComponent(i[0])]=decodeURIComponent(i[1])}return e}class Jt extends Error{constructor(e,t,s){super(e),this.description=t,this.context=s,this.type="TransportError"}}class Ve extends w{constructor(e){super(),this.writable=!1,ge(this,e),this.opts=e,this.query=e.query,this.socket=e.socket,this.supportsBinary=!e.forceBase64}onError(e,t,s){return super.emitReserved("error",new Jt(e,t,s)),this}open(){return this.readyState="opening",this.doOpen(),this}close(){return(this.readyState==="opening"||this.readyState==="open")&&(this.doClose(),this.onClose()),this}send(e){this.readyState==="open"&&this.write(e)}onOpen(){this.readyState="open",this.writable=!0,super.emitReserved("open")}onData(e){const t=je(e,this.socket.binaryType);this.onPacket(t)}onPacket(e){super.emitReserved("packet",e)}onClose(e){this.readyState="closed",super.emitReserved("close",e)}pause(e){}createUri(e,t={}){return e+"://"+this._hostname()+this._port()+this.opts.path+this._query(t)}_hostname(){const e=this.opts.hostname;return e.indexOf(":")===-1?e:"["+e+"]"}_port(){return this.opts.port&&(this.opts.secure&&Number(this.opts.port)!==443||!this.opts.secure&&Number(this.opts.port)!==80)?":"+this.opts.port:""}_query(e){const t=jt(e);return t.length?"?"+t:""}}class Gt extends Ve{constructor(){super(...arguments),this._polling=!1}get name(){return"polling"}doOpen(){this._poll()}pause(e){this.readyState="pausing";const t=()=>{this.readyState="paused",e()};if(this._polling||!this.writable){let s=0;this._polling&&(s++,this.once("pollComplete",function(){--s||t()})),this.writable||(s++,this.once("drain",function(){--s||t()}))}else t()}_poll(){this._polling=!0,this.doPoll(),this.emitReserved("poll")}onData(e){const t=s=>{if(this.readyState==="opening"&&s.type==="open"&&this.onOpen(),s.type==="close")return this.onClose({description:"transport closed by the server"}),!1;this.onPacket(s)};Bt(e,this.socket.binaryType).forEach(t),this.readyState!=="closed"&&(this._polling=!1,this.emitReserved("pollComplete"),this.readyState==="open"&&this._poll())}doClose(){const e=()=>{this.write([{type:"close"}])};this.readyState==="open"?e():this.once("open",e)}write(e){this.writable=!1,Pt(e,t=>{this.doWrite(t,()=>{this.writable=!0,this.emitReserved("drain")})})}uri(){const e=this.opts.secure?"https":"http",t=this.query||{};return this.opts.timestampRequests!==!1&&(t[this.opts.timestampParam]=ut()),!this.supportsBinary&&!t.sid&&(t.b64=1),this.createUri(e,t)}}let lt=!1;try{lt=typeof XMLHttpRequest<"u"&&"withCredentials"in new XMLHttpRequest}catch{}const Yt=lt;function Wt(){}class Kt extends Gt{constructor(e){if(super(e),typeof location<"u"){const t=location.protocol==="https:";let s=location.port;s||(s=t?"443":"80"),this.xd=typeof location<"u"&&e.hostname!==location.hostname||s!==e.port}}doWrite(e,t){const s=this.request({method:"POST",data:e});s.on("success",t),s.on("error",(r,i)=>{this.onError("xhr post error",r,i)})}doPoll(){const e=this.request();e.on("data",this.onData.bind(this)),e.on("error",(t,s)=>{this.onError("xhr poll error",t,s)}),this.pollXhr=e}}class N extends w{constructor(e,t,s){super(),this.createRequest=e,ge(this,s),this._opts=s,this._method=s.method||"GET",this._uri=t,this._data=s.data!==void 0?s.data:null,this._create()}_create(){var e;const t=ht(this._opts,"agent","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","autoUnref");t.xdomain=!!this._opts.xd;const s=this._xhr=this.createRequest(t);try{s.open(this._method,this._uri,!0);try{if(this._opts.extraHeaders){s.setDisableHeaderCheck&&s.setDisableHeaderCheck(!0);for(let r in this._opts.extraHeaders)this._opts.extraHeaders.hasOwnProperty(r)&&s.setRequestHeader(r,this._opts.extraHeaders[r])}}catch{}if(this._method==="POST")try{s.setRequestHeader("Content-type","text/plain;charset=UTF-8")}catch{}try{s.setRequestHeader("Accept","*/*")}catch{}(e=this._opts.cookieJar)===null||e===void 0||e.addCookies(s),"withCredentials"in s&&(s.withCredentials=this._opts.withCredentials),this._opts.requestTimeout&&(s.timeout=this._opts.requestTimeout),s.onreadystatechange=()=>{var r;s.readyState===3&&((r=this._opts.cookieJar)===null||r===void 0||r.parseCookies(s.getResponseHeader("set-cookie"))),s.readyState===4&&(s.status===200||s.status===1223?this._onLoad():this.setTimeoutFn(()=>{this._onError(typeof s.status=="number"?s.status:0)},0))},s.send(this._data)}catch(r){this.setTimeoutFn(()=>{this._onError(r)},0);return}typeof document<"u"&&(this._index=N.requestsCount++,N.requests[this._index]=this)}_onError(e){this.emitReserved("error",e,this._xhr),this._cleanup(!0)}_cleanup(e){if(!(typeof this._xhr>"u"||this._xhr===null)){if(this._xhr.onreadystatechange=Wt,e)try{this._xhr.abort()}catch{}typeof document<"u"&&delete N.requests[this._index],this._xhr=null}}_onLoad(){const e=this._xhr.responseText;e!==null&&(this.emitReserved("data",e),this.emitReserved("success"),this._cleanup())}abort(){this._cleanup()}}N.requestsCount=0;N.requests={};if(typeof document<"u"){if(typeof attachEvent=="function")attachEvent("onunload",et);else if(typeof addEventListener=="function"){const n="onpagehide"in S?"pagehide":"unload";addEventListener(n,et,!1)}}function et(){for(let n in N.requests)N.requests.hasOwnProperty(n)&&N.requests[n].abort()}const Xt=function(){const n=ft({xdomain:!1});return n&&n.responseType!==null}();class zt extends Kt{constructor(e){super(e);const t=e&&e.forceBase64;this.supportsBinary=Xt&&!t}request(e={}){return Object.assign(e,{xd:this.xd},this.opts),new N(ft,this.uri(),e)}}function ft(n){const e=n.xdomain;try{if(typeof XMLHttpRequest<"u"&&(!e||Yt))return new XMLHttpRequest}catch{}if(!e)try{return new S[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP")}catch{}}const dt=typeof navigator<"u"&&typeof navigator.product=="string"&&navigator.product.toLowerCase()==="reactnative";class Qt extends Ve{get name(){return"websocket"}doOpen(){const e=this.uri(),t=this.opts.protocols,s=dt?{}:ht(this.opts,"agent","perMessageDeflate","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","localAddress","protocolVersion","origin","maxPayload","family","checkServerIdentity");this.opts.extraHeaders&&(s.headers=this.opts.extraHeaders);try{this.ws=this.createSocket(e,t,s)}catch(r){return this.emitReserved("error",r)}this.ws.binaryType=this.socket.binaryType,this.addEventListeners()}addEventListeners(){this.ws.onopen=()=>{this.opts.autoUnref&&this.ws._socket.unref(),this.onOpen()},this.ws.onclose=e=>this.onClose({description:"websocket connection closed",context:e}),this.ws.onmessage=e=>this.onData(e.data),this.ws.onerror=e=>this.onError("websocket error",e)}write(e){this.writable=!1;for(let t=0;t<e.length;t++){const s=e[t],r=t===e.length-1;He(s,this.supportsBinary,i=>{try{this.doWrite(s,i)}catch{}r&&me(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){typeof this.ws<"u"&&(this.ws.onerror=()=>{},this.ws.close(),this.ws=null)}uri(){const e=this.opts.secure?"wss":"ws",t=this.query||{};return this.opts.timestampRequests&&(t[this.opts.timestampParam]=ut()),this.supportsBinary||(t.b64=1),this.createUri(e,t)}}const Ee=S.WebSocket||S.MozWebSocket;class Zt extends Qt{createSocket(e,t,s){return dt?new Ee(e,t,s):t?new Ee(e,t):new Ee(e)}doWrite(e,t){this.ws.send(t)}}class es extends Ve{get name(){return"webtransport"}doOpen(){try{this._transport=new WebTransport(this.createUri("https"),this.opts.transportOptions[this.name])}catch(e){return this.emitReserved("error",e)}this._transport.closed.then(()=>{this.onClose()}).catch(e=>{this.onError("webtransport error",e)}),this._transport.ready.then(()=>{this._transport.createBidirectionalStream().then(e=>{const t=It(Number.MAX_SAFE_INTEGER,this.socket.binaryType),s=e.readable.pipeThrough(t).getReader(),r=xt();r.readable.pipeTo(e.writable),this._writer=r.writable.getWriter();const i=()=>{s.read().then(({done:h,value:f})=>{h||(this.onPacket(f),i())}).catch(h=>{})};i();const o={type:"open"};this.query.sid&&(o.data=`{"sid":"${this.query.sid}"}`),this._writer.write(o).then(()=>this.onOpen())})})}write(e){this.writable=!1;for(let t=0;t<e.length;t++){const s=e[t],r=t===e.length-1;this._writer.write(s).then(()=>{r&&me(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){var e;(e=this._transport)===null||e===void 0||e.close()}}const ts={websocket:Zt,webtransport:es,polling:zt},ss=/^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,ns=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];function Oe(n){if(n.length>8e3)throw"URI too long";const e=n,t=n.indexOf("["),s=n.indexOf("]");t!=-1&&s!=-1&&(n=n.substring(0,t)+n.substring(t,s).replace(/:/g,";")+n.substring(s,n.length));let r=ss.exec(n||""),i={},o=14;for(;o--;)i[ns[o]]=r[o]||"";return t!=-1&&s!=-1&&(i.source=e,i.host=i.host.substring(1,i.host.length-1).replace(/;/g,":"),i.authority=i.authority.replace("[","").replace("]","").replace(/;/g,":"),i.ipv6uri=!0),i.pathNames=rs(i,i.path),i.queryKey=is(i,i.query),i}function rs(n,e){const t=/\/{2,9}/g,s=e.replace(t,"/").split("/");return(e.slice(0,1)=="/"||e.length===0)&&s.splice(0,1),e.slice(-1)=="/"&&s.splice(s.length-1,1),s}function is(n,e){const t={};return e.replace(/(?:^|&)([^&=]*)=?([^&]*)/g,function(s,r,i){r&&(t[r]=i)}),t}const Ce=typeof addEventListener=="function"&&typeof removeEventListener=="function",he=[];Ce&&addEventListener("offline",()=>{he.forEach(n=>n())},!1);class M extends w{constructor(e,t){if(super(),this.binaryType=qt,this.writeBuffer=[],this._prevBufferLen=0,this._pingInterval=-1,this._pingTimeout=-1,this._maxPayload=-1,this._pingTimeoutTime=1/0,e&&typeof e=="object"&&(t=e,e=null),e){const s=Oe(e);t.hostname=s.host,t.secure=s.protocol==="https"||s.protocol==="wss",t.port=s.port,s.query&&(t.query=s.query)}else t.host&&(t.hostname=Oe(t.host).host);ge(this,t),this.secure=t.secure!=null?t.secure:typeof location<"u"&&location.protocol==="https:",t.hostname&&!t.port&&(t.port=this.secure?"443":"80"),this.hostname=t.hostname||(typeof location<"u"?location.hostname:"localhost"),this.port=t.port||(typeof location<"u"&&location.port?location.port:this.secure?"443":"80"),this.transports=[],this._transportsByName={},t.transports.forEach(s=>{const r=s.prototype.name;this.transports.push(r),this._transportsByName[r]=s}),this.opts=Object.assign({path:"/engine.io",agent:!1,withCredentials:!1,upgrade:!0,timestampParam:"t",rememberUpgrade:!1,addTrailingSlash:!0,rejectUnauthorized:!0,perMessageDeflate:{threshold:1024},transportOptions:{},closeOnBeforeunload:!1},t),this.opts.path=this.opts.path.replace(/\/$/,"")+(this.opts.addTrailingSlash?"/":""),typeof this.opts.query=="string"&&(this.opts.query=Vt(this.opts.query)),Ce&&(this.opts.closeOnBeforeunload&&(this._beforeunloadEventListener=()=>{this.transport&&(this.transport.removeAllListeners(),this.transport.close())},addEventListener("beforeunload",this._beforeunloadEventListener,!1)),this.hostname!=="localhost"&&(this._offlineEventListener=()=>{this._onClose("transport close",{description:"network connection lost"})},he.push(this._offlineEventListener))),this.opts.withCredentials&&(this._cookieJar=void 0),this._open()}createTransport(e){const t=Object.assign({},this.opts.query);t.EIO=ct,t.transport=e,this.id&&(t.sid=this.id);const s=Object.assign({},this.opts,{query:t,socket:this,hostname:this.hostname,secure:this.secure,port:this.port},this.opts.transportOptions[e]);return new this._transportsByName[e](s)}_open(){if(this.transports.length===0){this.setTimeoutFn(()=>{this.emitReserved("error","No transports available")},0);return}const e=this.opts.rememberUpgrade&&M.priorWebsocketSuccess&&this.transports.indexOf("websocket")!==-1?"websocket":this.transports[0];this.readyState="opening";const t=this.createTransport(e);t.open(),this.setTransport(t)}setTransport(e){this.transport&&this.transport.removeAllListeners(),this.transport=e,e.on("drain",this._onDrain.bind(this)).on("packet",this._onPacket.bind(this)).on("error",this._onError.bind(this)).on("close",t=>this._onClose("transport close",t))}onOpen(){this.readyState="open",M.priorWebsocketSuccess=this.transport.name==="websocket",this.emitReserved("open"),this.flush()}_onPacket(e){if(this.readyState==="opening"||this.readyState==="open"||this.readyState==="closing")switch(this.emitReserved("packet",e),this.emitReserved("heartbeat"),e.type){case"open":this.onHandshake(JSON.parse(e.data));break;case"ping":this._sendPacket("pong"),this.emitReserved("ping"),this.emitReserved("pong"),this._resetPingTimeout();break;case"error":const t=new Error("server error");t.code=e.data,this._onError(t);break;case"message":this.emitReserved("data",e.data),this.emitReserved("message",e.data);break}}onHandshake(e){this.emitReserved("handshake",e),this.id=e.sid,this.transport.query.sid=e.sid,this._pingInterval=e.pingInterval,this._pingTimeout=e.pingTimeout,this._maxPayload=e.maxPayload,this.onOpen(),this.readyState!=="closed"&&this._resetPingTimeout()}_resetPingTimeout(){this.clearTimeoutFn(this._pingTimeoutTimer);const e=this._pingInterval+this._pingTimeout;this._pingTimeoutTime=Date.now()+e,this._pingTimeoutTimer=this.setTimeoutFn(()=>{this._onClose("ping timeout")},e),this.opts.autoUnref&&this._pingTimeoutTimer.unref()}_onDrain(){this.writeBuffer.splice(0,this._prevBufferLen),this._prevBufferLen=0,this.writeBuffer.length===0?this.emitReserved("drain"):this.flush()}flush(){if(this.readyState!=="closed"&&this.transport.writable&&!this.upgrading&&this.writeBuffer.length){const e=this._getWritablePackets();this.transport.send(e),this._prevBufferLen=e.length,this.emitReserved("flush")}}_getWritablePackets(){if(!(this._maxPayload&&this.transport.name==="polling"&&this.writeBuffer.length>1))return this.writeBuffer;let t=1;for(let s=0;s<this.writeBuffer.length;s++){const r=this.writeBuffer[s].data;if(r&&(t+=Mt(r)),s>0&&t>this._maxPayload)return this.writeBuffer.slice(0,s);t+=2}return this.writeBuffer}_hasPingExpired(){if(!this._pingTimeoutTime)return!0;const e=Date.now()>this._pingTimeoutTime;return e&&(this._pingTimeoutTime=0,me(()=>{this._onClose("ping timeout")},this.setTimeoutFn)),e}write(e,t,s){return this._sendPacket("message",e,t,s),this}send(e,t,s){return this._sendPacket("message",e,t,s),this}_sendPacket(e,t,s,r){if(typeof t=="function"&&(r=t,t=void 0),typeof s=="function"&&(r=s,s=null),this.readyState==="closing"||this.readyState==="closed")return;s=s||{},s.compress=s.compress!==!1;const i={type:e,data:t,options:s};this.emitReserved("packetCreate",i),this.writeBuffer.push(i),r&&this.once("flush",r),this.flush()}close(){const e=()=>{this._onClose("forced close"),this.transport.close()},t=()=>{this.off("upgrade",t),this.off("upgradeError",t),e()},s=()=>{this.once("upgrade",t),this.once("upgradeError",t)};return(this.readyState==="opening"||this.readyState==="open")&&(this.readyState="closing",this.writeBuffer.length?this.once("drain",()=>{this.upgrading?s():e()}):this.upgrading?s():e()),this}_onError(e){if(M.priorWebsocketSuccess=!1,this.opts.tryAllTransports&&this.transports.length>1&&this.readyState==="opening")return this.transports.shift(),this._open();this.emitReserved("error",e),this._onClose("transport error",e)}_onClose(e,t){if(this.readyState==="opening"||this.readyState==="open"||this.readyState==="closing"){if(this.clearTimeoutFn(this._pingTimeoutTimer),this.transport.removeAllListeners("close"),this.transport.close(),this.transport.removeAllListeners(),Ce&&(this._beforeunloadEventListener&&removeEventListener("beforeunload",this._beforeunloadEventListener,!1),this._offlineEventListener)){const s=he.indexOf(this._offlineEventListener);s!==-1&&he.splice(s,1)}this.readyState="closed",this.id=null,this.emitReserved("close",e,t),this.writeBuffer=[],this._prevBufferLen=0}}}M.protocol=ct;class os extends M{constructor(){super(...arguments),this._upgrades=[]}onOpen(){if(super.onOpen(),this.readyState==="open"&&this.opts.upgrade)for(let e=0;e<this._upgrades.length;e++)this._probe(this._upgrades[e])}_probe(e){let t=this.createTransport(e),s=!1;M.priorWebsocketSuccess=!1;const r=()=>{s||(t.send([{type:"ping",data:"probe"}]),t.once("packet",g=>{if(!s)if(g.type==="pong"&&g.data==="probe"){if(this.upgrading=!0,this.emitReserved("upgrading",t),!t)return;M.priorWebsocketSuccess=t.name==="websocket",this.transport.pause(()=>{s||this.readyState!=="closed"&&(y(),this.setTransport(t),t.send([{type:"upgrade"}]),this.emitReserved("upgrade",t),t=null,this.upgrading=!1,this.flush())})}else{const R=new Error("probe error");R.transport=t.name,this.emitReserved("upgradeError",R)}}))};function i(){s||(s=!0,y(),t.close(),t=null)}const o=g=>{const R=new Error("probe error: "+g);R.transport=t.name,i(),this.emitReserved("upgradeError",R)};function h(){o("transport closed")}function f(){o("socket closed")}function m(g){t&&g.name!==t.name&&i()}const y=()=>{t.removeListener("open",r),t.removeListener("error",o),t.removeListener("close",h),this.off("close",f),this.off("upgrading",m)};t.once("open",r),t.once("error",o),t.once("close",h),this.once("close",f),this.once("upgrading",m),this._upgrades.indexOf("webtransport")!==-1&&e!=="webtransport"?this.setTimeoutFn(()=>{s||t.open()},200):t.open()}onHandshake(e){this._upgrades=this._filterUpgrades(e.upgrades),super.onHandshake(e)}_filterUpgrades(e){const t=[];for(let s=0;s<e.length;s++)~this.transports.indexOf(e[s])&&t.push(e[s]);return t}}let as=class extends os{constructor(e,t={}){const s=typeof e=="object",r=s?{...e}:{...t};(!r.transports||r.transports&&typeof r.transports[0]=="string")&&(r.transports=(r.transports||["polling","websocket","webtransport"]).map(i=>ts[i]).filter(i=>!!i)),super(s?r:e,r)}};function cs(n,e="",t){let s=n;t=t||typeof location<"u"&&location,n==null&&(n=t.protocol+"//"+t.host),typeof n=="string"&&(n.charAt(0)==="/"&&(n.charAt(1)==="/"?n=t.protocol+n:n=t.host+n),/^(https?|wss?):\/\//.test(n)||(typeof t<"u"?n=t.protocol+"//"+n:n="https://"+n),s=Oe(n)),s.port||(/^(http|ws)$/.test(s.protocol)?s.port="80":/^(http|ws)s$/.test(s.protocol)&&(s.port="443")),s.path=s.path||"/";const i=s.host.indexOf(":")!==-1?"["+s.host+"]":s.host;return s.id=s.protocol+"://"+i+":"+s.port+e,s.href=s.protocol+"://"+i+(t&&t.port===s.port?"":":"+s.port),s}const hs=typeof ArrayBuffer=="function",us=n=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(n):n.buffer instanceof ArrayBuffer,pt=Object.prototype.toString,ls=typeof Blob=="function"||typeof Blob<"u"&&pt.call(Blob)==="[object BlobConstructor]",fs=typeof File=="function"||typeof File<"u"&&pt.call(File)==="[object FileConstructor]";function Je(n){return hs&&(n instanceof ArrayBuffer||us(n))||ls&&n instanceof Blob||fs&&n instanceof File}function ue(n,e){if(!n||typeof n!="object")return!1;if(Array.isArray(n)){for(let t=0,s=n.length;t<s;t++)if(ue(n[t]))return!0;return!1}if(Je(n))return!0;if(n.toJSON&&typeof n.toJSON=="function"&&arguments.length===1)return ue(n.toJSON(),!0);for(const t in n)if(Object.prototype.hasOwnProperty.call(n,t)&&ue(n[t]))return!0;return!1}function ds(n){const e=[],t=n.data,s=n;return s.data=Re(t,e),s.attachments=e.length,{packet:s,buffers:e}}function Re(n,e){if(!n)return n;if(Je(n)){const t={_placeholder:!0,num:e.length};return e.push(n),t}else if(Array.isArray(n)){const t=new Array(n.length);for(let s=0;s<n.length;s++)t[s]=Re(n[s],e);return t}else if(typeof n=="object"&&!(n instanceof Date)){const t={};for(const s in n)Object.prototype.hasOwnProperty.call(n,s)&&(t[s]=Re(n[s],e));return t}return n}function ps(n,e){return n.data=$e(n.data,e),delete n.attachments,n}function $e(n,e){if(!n)return n;if(n&&n._placeholder===!0){if(typeof n.num=="number"&&n.num>=0&&n.num<e.length)return e[n.num];throw new Error("illegal attachments")}else if(Array.isArray(n))for(let t=0;t<n.length;t++)n[t]=$e(n[t],e);else if(typeof n=="object")for(const t in n)Object.prototype.hasOwnProperty.call(n,t)&&(n[t]=$e(n[t],e));return n}const ys=["connect","connect_error","disconnect","disconnecting","newListener","removeListener"];var p;(function(n){n[n.CONNECT=0]="CONNECT",n[n.DISCONNECT=1]="DISCONNECT",n[n.EVENT=2]="EVENT",n[n.ACK=3]="ACK",n[n.CONNECT_ERROR=4]="CONNECT_ERROR",n[n.BINARY_EVENT=5]="BINARY_EVENT",n[n.BINARY_ACK=6]="BINARY_ACK"})(p||(p={}));class ms{constructor(e){this.replacer=e}encode(e){return(e.type===p.EVENT||e.type===p.ACK)&&ue(e)?this.encodeAsBinary({type:e.type===p.EVENT?p.BINARY_EVENT:p.BINARY_ACK,nsp:e.nsp,data:e.data,id:e.id}):[this.encodeAsString(e)]}encodeAsString(e){let t=""+e.type;return(e.type===p.BINARY_EVENT||e.type===p.BINARY_ACK)&&(t+=e.attachments+"-"),e.nsp&&e.nsp!=="/"&&(t+=e.nsp+","),e.id!=null&&(t+=e.id),e.data!=null&&(t+=JSON.stringify(e.data,this.replacer)),t}encodeAsBinary(e){const t=ds(e),s=this.encodeAsString(t.packet),r=t.buffers;return r.unshift(s),r}}class Ge extends w{constructor(e){super(),this.opts=Object.assign({reviver:void 0,maxAttachments:10},typeof e=="function"?{reviver:e}:e)}add(e){let t;if(typeof e=="string"){if(this.reconstructor)throw new Error("got plaintext data when reconstructing a packet");t=this.decodeString(e);const s=t.type===p.BINARY_EVENT;s||t.type===p.BINARY_ACK?(t.type=s?p.EVENT:p.ACK,this.reconstructor=new gs(t),t.attachments===0&&super.emitReserved("decoded",t)):super.emitReserved("decoded",t)}else if(Je(e)||e.base64)if(this.reconstructor)t=this.reconstructor.takeBinaryData(e),t&&(this.reconstructor=null,super.emitReserved("decoded",t));else throw new Error("got binary data when not reconstructing a packet");else throw new Error("Unknown type: "+e)}decodeString(e){let t=0;const s={type:Number(e.charAt(0))};if(p[s.type]===void 0)throw new Error("unknown packet type "+s.type);if(s.type===p.BINARY_EVENT||s.type===p.BINARY_ACK){const i=t+1;for(;e.charAt(++t)!=="-"&&t!=e.length;);const o=e.substring(i,t);if(o!=Number(o)||e.charAt(t)!=="-")throw new Error("Illegal attachments");const h=Number(o);if(!ws(h)||h<0)throw new Error("Illegal attachments");if(h>this.opts.maxAttachments)throw new Error("too many attachments");s.attachments=h}if(e.charAt(t+1)==="/"){const i=t+1;for(;++t&&!(e.charAt(t)===","||t===e.length););s.nsp=e.substring(i,t)}else s.nsp="/";const r=e.charAt(t+1);if(r!==""&&Number(r)==r){const i=t+1;for(;++t;){const o=e.charAt(t);if(o==null||Number(o)!=o){--t;break}if(t===e.length)break}s.id=Number(e.substring(i,t+1))}if(e.charAt(++t)){const i=this.tryParse(e.substr(t));if(Ge.isPayloadValid(s.type,i))s.data=i;else throw new Error("invalid payload")}return s}tryParse(e){try{return JSON.parse(e,this.opts.reviver)}catch{return!1}}static isPayloadValid(e,t){switch(e){case p.CONNECT:return tt(t);case p.DISCONNECT:return t===void 0;case p.CONNECT_ERROR:return typeof t=="string"||tt(t);case p.EVENT:case p.BINARY_EVENT:return Array.isArray(t)&&(typeof t[0]=="number"||typeof t[0]=="string"&&ys.indexOf(t[0])===-1);case p.ACK:case p.BINARY_ACK:return Array.isArray(t)}}destroy(){this.reconstructor&&(this.reconstructor.finishedReconstruction(),this.reconstructor=null)}}class gs{constructor(e){this.packet=e,this.buffers=[],this.reconPack=e}takeBinaryData(e){if(this.buffers.push(e),this.buffers.length===this.reconPack.attachments){const t=ps(this.reconPack,this.buffers);return this.finishedReconstruction(),t}return null}finishedReconstruction(){this.reconPack=null,this.buffers=[]}}const ws=Number.isInteger||function(n){return typeof n=="number"&&isFinite(n)&&Math.floor(n)===n};function tt(n){return Object.prototype.toString.call(n)==="[object Object]"}const _s=Object.freeze(Object.defineProperty({__proto__:null,Decoder:Ge,Encoder:ms,get PacketType(){return p}},Symbol.toStringTag,{value:"Module"}));function C(n,e,t){return n.on(e,t),function(){n.off(e,t)}}const bs=Object.freeze({connect:1,connect_error:1,disconnect:1,disconnecting:1,newListener:1,removeListener:1});class yt extends w{constructor(e,t,s){super(),this.connected=!1,this.recovered=!1,this.receiveBuffer=[],this.sendBuffer=[],this._queue=[],this._queueSeq=0,this.ids=0,this.acks={},this.flags={},this.io=e,this.nsp=t,s&&s.auth&&(this.auth=s.auth),this._opts=Object.assign({},s),this.io._autoConnect&&this.open()}get disconnected(){return!this.connected}subEvents(){if(this.subs)return;const e=this.io;this.subs=[C(e,"open",this.onopen.bind(this)),C(e,"packet",this.onpacket.bind(this)),C(e,"error",this.onerror.bind(this)),C(e,"close",this.onclose.bind(this))]}get active(){return!!this.subs}connect(){return this.connected?this:(this.subEvents(),this.io._reconnecting||this.io.open(),this.io._readyState==="open"&&this.onopen(),this)}open(){return this.connect()}send(...e){return e.unshift("message"),this.emit.apply(this,e),this}emit(e,...t){var s,r,i;if(bs.hasOwnProperty(e))throw new Error('"'+e.toString()+'" is a reserved event name');if(t.unshift(e),this._opts.retries&&!this.flags.fromQueue&&!this.flags.volatile)return this._addToQueue(t),this;const o={type:p.EVENT,data:t};if(o.options={},o.options.compress=this.flags.compress!==!1,typeof t[t.length-1]=="function"){const y=this.ids++,g=t.pop();this._registerAckCallback(y,g),o.id=y}const h=(r=(s=this.io.engine)===null||s===void 0?void 0:s.transport)===null||r===void 0?void 0:r.writable,f=this.connected&&!(!((i=this.io.engine)===null||i===void 0)&&i._hasPingExpired());return this.flags.volatile&&!h||(f?(this.notifyOutgoingListeners(o),this.packet(o)):this.sendBuffer.push(o)),this.flags={},this}_registerAckCallback(e,t){var s;const r=(s=this.flags.timeout)!==null&&s!==void 0?s:this._opts.ackTimeout;if(r===void 0){this.acks[e]=t;return}const i=this.io.setTimeoutFn(()=>{delete this.acks[e];for(let h=0;h<this.sendBuffer.length;h++)this.sendBuffer[h].id===e&&this.sendBuffer.splice(h,1);t.call(this,new Error("operation has timed out"))},r),o=(...h)=>{this.io.clearTimeoutFn(i),t.apply(this,h)};o.withError=!0,this.acks[e]=o}emitWithAck(e,...t){return new Promise((s,r)=>{const i=(o,h)=>o?r(o):s(h);i.withError=!0,t.push(i),this.emit(e,...t)})}_addToQueue(e){let t;typeof e[e.length-1]=="function"&&(t=e.pop());const s={id:this._queueSeq++,tryCount:0,pending:!1,args:e,flags:Object.assign({fromQueue:!0},this.flags)};e.push((r,...i)=>(this._queue[0],r!==null?s.tryCount>this._opts.retries&&(this._queue.shift(),t&&t(r)):(this._queue.shift(),t&&t(null,...i)),s.pending=!1,this._drainQueue())),this._queue.push(s),this._drainQueue()}_drainQueue(e=!1){if(!this.connected||this._queue.length===0)return;const t=this._queue[0];t.pending&&!e||(t.pending=!0,t.tryCount++,this.flags=t.flags,this.emit.apply(this,t.args))}packet(e){e.nsp=this.nsp,this.io._packet(e)}onopen(){typeof this.auth=="function"?this.auth(e=>{this._sendConnectPacket(e)}):this._sendConnectPacket(this.auth)}_sendConnectPacket(e){this.packet({type:p.CONNECT,data:this._pid?Object.assign({pid:this._pid,offset:this._lastOffset},e):e})}onerror(e){this.connected||this.emitReserved("connect_error",e)}onclose(e,t){this.connected=!1,delete this.id,this.emitReserved("disconnect",e,t),this._clearAcks()}_clearAcks(){Object.keys(this.acks).forEach(e=>{if(!this.sendBuffer.some(s=>String(s.id)===e)){const s=this.acks[e];delete this.acks[e],s.withError&&s.call(this,new Error("socket has been disconnected"))}})}onpacket(e){if(e.nsp===this.nsp)switch(e.type){case p.CONNECT:e.data&&e.data.sid?this.onconnect(e.data.sid,e.data.pid):this.emitReserved("connect_error",new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));break;case p.EVENT:case p.BINARY_EVENT:this.onevent(e);break;case p.ACK:case p.BINARY_ACK:this.onack(e);break;case p.DISCONNECT:this.ondisconnect();break;case p.CONNECT_ERROR:this.destroy();const s=new Error(e.data.message);s.data=e.data.data,this.emitReserved("connect_error",s);break}}onevent(e){const t=e.data||[];e.id!=null&&t.push(this.ack(e.id)),this.connected?this.emitEvent(t):this.receiveBuffer.push(Object.freeze(t))}emitEvent(e){if(this._anyListeners&&this._anyListeners.length){const t=this._anyListeners.slice();for(const s of t)s.apply(this,e)}super.emit.apply(this,e),this._pid&&e.length&&typeof e[e.length-1]=="string"&&(this._lastOffset=e[e.length-1])}ack(e){const t=this;let s=!1;return function(...r){s||(s=!0,t.packet({type:p.ACK,id:e,data:r}))}}onack(e){const t=this.acks[e.id];typeof t=="function"&&(delete this.acks[e.id],t.withError&&e.data.unshift(null),t.apply(this,e.data))}onconnect(e,t){this.id=e,this.recovered=t&&this._pid===t,this._pid=t,this.connected=!0,this.emitBuffered(),this._drainQueue(!0),this.emitReserved("connect")}emitBuffered(){this.receiveBuffer.forEach(e=>this.emitEvent(e)),this.receiveBuffer=[],this.sendBuffer.forEach(e=>{this.notifyOutgoingListeners(e),this.packet(e)}),this.sendBuffer=[]}ondisconnect(){this.destroy(),this.onclose("io server disconnect")}destroy(){this.subs&&(this.subs.forEach(e=>e()),this.subs=void 0),this.io._destroy(this)}disconnect(){return this.connected&&this.packet({type:p.DISCONNECT}),this.destroy(),this.connected&&this.onclose("io client disconnect"),this}close(){return this.disconnect()}compress(e){return this.flags.compress=e,this}get volatile(){return this.flags.volatile=!0,this}timeout(e){return this.flags.timeout=e,this}onAny(e){return this._anyListeners=this._anyListeners||[],this._anyListeners.push(e),this}prependAny(e){return this._anyListeners=this._anyListeners||[],this._anyListeners.unshift(e),this}offAny(e){if(!this._anyListeners)return this;if(e){const t=this._anyListeners;for(let s=0;s<t.length;s++)if(e===t[s])return t.splice(s,1),this}else this._anyListeners=[];return this}listenersAny(){return this._anyListeners||[]}onAnyOutgoing(e){return this._anyOutgoingListeners=this._anyOutgoingListeners||[],this._anyOutgoingListeners.push(e),this}prependAnyOutgoing(e){return this._anyOutgoingListeners=this._anyOutgoingListeners||[],this._anyOutgoingListeners.unshift(e),this}offAnyOutgoing(e){if(!this._anyOutgoingListeners)return this;if(e){const t=this._anyOutgoingListeners;for(let s=0;s<t.length;s++)if(e===t[s])return t.splice(s,1),this}else this._anyOutgoingListeners=[];return this}listenersAnyOutgoing(){return this._anyOutgoingListeners||[]}notifyOutgoingListeners(e){if(this._anyOutgoingListeners&&this._anyOutgoingListeners.length){const t=this._anyOutgoingListeners.slice();for(const s of t)s.apply(this,e.data)}}}function Q(n){n=n||{},this.ms=n.min||100,this.max=n.max||1e4,this.factor=n.factor||2,this.jitter=n.jitter>0&&n.jitter<=1?n.jitter:0,this.attempts=0}Q.prototype.duration=function(){var n=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var e=Math.random(),t=Math.floor(e*this.jitter*n);n=Math.floor(e*10)&1?n+t:n-t}return Math.min(n,this.max)|0};Q.prototype.reset=function(){this.attempts=0};Q.prototype.setMin=function(n){this.ms=n};Q.prototype.setMax=function(n){this.max=n};Q.prototype.setJitter=function(n){this.jitter=n};class Ne extends w{constructor(e,t){var s;super(),this.nsps={},this.subs=[],e&&typeof e=="object"&&(t=e,e=void 0),t=t||{},t.path=t.path||"/socket.io",this.opts=t,ge(this,t),this.reconnection(t.reconnection!==!1),this.reconnectionAttempts(t.reconnectionAttempts||1/0),this.reconnectionDelay(t.reconnectionDelay||1e3),this.reconnectionDelayMax(t.reconnectionDelayMax||5e3),this.randomizationFactor((s=t.randomizationFactor)!==null&&s!==void 0?s:.5),this.backoff=new Q({min:this.reconnectionDelay(),max:this.reconnectionDelayMax(),jitter:this.randomizationFactor()}),this.timeout(t.timeout==null?2e4:t.timeout),this._readyState="closed",this.uri=e;const r=t.parser||_s;this.encoder=new r.Encoder,this.decoder=new r.Decoder,this._autoConnect=t.autoConnect!==!1,this._autoConnect&&this.open()}reconnection(e){return arguments.length?(this._reconnection=!!e,e||(this.skipReconnect=!0),this):this._reconnection}reconnectionAttempts(e){return e===void 0?this._reconnectionAttempts:(this._reconnectionAttempts=e,this)}reconnectionDelay(e){var t;return e===void 0?this._reconnectionDelay:(this._reconnectionDelay=e,(t=this.backoff)===null||t===void 0||t.setMin(e),this)}randomizationFactor(e){var t;return e===void 0?this._randomizationFactor:(this._randomizationFactor=e,(t=this.backoff)===null||t===void 0||t.setJitter(e),this)}reconnectionDelayMax(e){var t;return e===void 0?this._reconnectionDelayMax:(this._reconnectionDelayMax=e,(t=this.backoff)===null||t===void 0||t.setMax(e),this)}timeout(e){return arguments.length?(this._timeout=e,this):this._timeout}maybeReconnectOnOpen(){!this._reconnecting&&this._reconnection&&this.backoff.attempts===0&&this.reconnect()}open(e){if(~this._readyState.indexOf("open"))return this;this.engine=new as(this.uri,this.opts);const t=this.engine,s=this;this._readyState="opening",this.skipReconnect=!1;const r=C(t,"open",function(){s.onopen(),e&&e()}),i=h=>{this.cleanup(),this._readyState="closed",this.emitReserved("error",h),e?e(h):this.maybeReconnectOnOpen()},o=C(t,"error",i);if(this._timeout!==!1){const h=this._timeout,f=this.setTimeoutFn(()=>{r(),i(new Error("timeout")),t.close()},h);this.opts.autoUnref&&f.unref(),this.subs.push(()=>{this.clearTimeoutFn(f)})}return this.subs.push(r),this.subs.push(o),this}connect(e){return this.open(e)}onopen(){this.cleanup(),this._readyState="open",this.emitReserved("open");const e=this.engine;this.subs.push(C(e,"ping",this.onping.bind(this)),C(e,"data",this.ondata.bind(this)),C(e,"error",this.onerror.bind(this)),C(e,"close",this.onclose.bind(this)),C(this.decoder,"decoded",this.ondecoded.bind(this)))}onping(){this.emitReserved("ping")}ondata(e){try{this.decoder.add(e)}catch(t){this.onclose("parse error",t)}}ondecoded(e){me(()=>{this.emitReserved("packet",e)},this.setTimeoutFn)}onerror(e){this.emitReserved("error",e)}socket(e,t){let s=this.nsps[e];return s?this._autoConnect&&!s.active&&s.connect():(s=new yt(this,e,t),this.nsps[e]=s),s}_destroy(e){const t=Object.keys(this.nsps);for(const s of t)if(this.nsps[s].active)return;this._close()}_packet(e){const t=this.encoder.encode(e);for(let s=0;s<t.length;s++)this.engine.write(t[s],e.options)}cleanup(){this.subs.forEach(e=>e()),this.subs.length=0,this.decoder.destroy()}_close(){this.skipReconnect=!0,this._reconnecting=!1,this.onclose("forced close")}disconnect(){return this._close()}onclose(e,t){var s;this.cleanup(),(s=this.engine)===null||s===void 0||s.close(),this.backoff.reset(),this._readyState="closed",this.emitReserved("close",e,t),this._reconnection&&!this.skipReconnect&&this.reconnect()}reconnect(){if(this._reconnecting||this.skipReconnect)return this;const e=this;if(this.backoff.attempts>=this._reconnectionAttempts)this.backoff.reset(),this.emitReserved("reconnect_failed"),this._reconnecting=!1;else{const t=this.backoff.duration();this._reconnecting=!0;const s=this.setTimeoutFn(()=>{e.skipReconnect||(this.emitReserved("reconnect_attempt",e.backoff.attempts),!e.skipReconnect&&e.open(r=>{r?(e._reconnecting=!1,e.reconnect(),this.emitReserved("reconnect_error",r)):e.onreconnect()}))},t);this.opts.autoUnref&&s.unref(),this.subs.push(()=>{this.clearTimeoutFn(s)})}}onreconnect(){const e=this.backoff.attempts;this._reconnecting=!1,this.backoff.reset(),this.emitReserved("reconnect",e)}}const Z={};function se(n,e){typeof n=="object"&&(e=n,n=void 0),e=e||{};const t=cs(n,e.path||"/socket.io"),s=t.source,r=t.id,i=t.path,o=Z[r]&&i in Z[r].nsps,h=e.forceNew||e["force new connection"]||e.multiplex===!1||o;let f;return h?f=new Ne(s,e):(Z[r]||(Z[r]=new Ne(s,e)),f=Z[r]),t.query&&!e.query&&(e.query=t.queryKey),f.socket(t.path,e)}Object.assign(se,{Manager:Ne,Socket:yt,io:se,connect:se});const Pe=100;function Ts(n){try{const e=JSON.parse(n);if(e&&typeof e=="object"){const t=e;return{message:typeof t.message=="string"?t.message:void 0,code:typeof t.code=="string"?t.code:void 0,details:t.details}}}catch{}return{}}function Es(n){if(!n||typeof n!="object")return;const e=n.retryAfter;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}class we extends Error{constructor(t,s,r,i){const o=Ts(r);super(o.message??`${s||"Request failed"} (${t})`);E(this,"status");E(this,"code");E(this,"details");E(this,"body");E(this,"retryAfter");this.name="RequestError",this.status=t,this.code=o.code,this.details=o.details,this.body=r,this.retryAfter=i??Es(o.details)}}const $="item/folder",d="item",L="processor",vs="npm-registry",B="hidden",ve="FILE",ke="TOOL",Ae="APP",ks=500,st=3e4,As=.25,Ss=n=>new Promise(e=>setTimeout(e,n));function Os(n){var r,i;const e=(i=(r=n.headers)==null?void 0:r.get)==null?void 0:i.call(r,"Retry-After");if(!e)return;const t=Number(e);if(Number.isFinite(t))return Math.max(0,t);const s=Date.parse(e);if(!Number.isNaN(s))return Math.max(0,(s-Date.now())/1e3)}function Cs(n){return n instanceof we?n.status===429||n.status>=500:!0}function Rs(n,e){const t=Math.min(ks*2**e,st),s=t*As*Math.random(),r=n instanceof we&&n.retryAfter!=null?n.retryAfter*1e3:void 0;return r!=null?Math.min(r,st)+s:t+s}var c,Be,l,q,te,le,fe,xe,Ie,mt;const We=class We{constructor(e,t,s){_(this,c);E(this,"apiUrl");E(this,"accessToken");E(this,"wsUrl");E(this,"retries");E(this,"useBearer");E(this,"builtInGlobals",null);E(this,"localServerUrl",null);E(this,"context");const{retries:r=0,useBearer:i=!1,localServerUrl:o}=s||{};let h=t;if(h.charAt(h.length-1)==="/"&&(h=h.slice(0,-1)),this.apiUrl=`${h}/api`,this.accessToken=e,this.wsUrl=`${h}?accessToken=${e}`,this.retries=r,this.useBearer=i,this.context={appId:"",projectId:"",accessToken:e,apiUrl:t},o){let f=o;f.charAt(f.length-1)==="/"&&(f=f.slice(0,-1)),this.localServerUrl=f}}static fromPlatformContext(e){const t=(typeof window<"u"?window.__THATOPEN_CONTEXT__:null)||{appId:"",projectId:"",accessToken:"",apiUrl:""},s=new We(t.accessToken,t.apiUrl,{...e,useBearer:!0});return s.context=t,s}setRetries(e){this.retries=e}setBuiltInGlobals(e){this.builtInGlobals=e}get socketOrigin(){return this.wsUrl.split("?")[0]}async resolveAccessToken(){return this.accessToken}async request(e,t,s){return a(this,c,l).call(this,e,t,s)}async listFiles(e){const{folderId:t,archived:s,projectId:r}=e||{};return t?await a(this,c,l).call(this,"GET",`${$}/${t}/items`,{query:{itemType:ve,archived:s}}):await a(this,c,l).call(this,"GET",`${d}`,{query:{itemType:ve,archived:s,...r&&{projectId:r}}})}async getFile(e,t){return await a(this,c,Ie).call(this,e,t)}async createFile(e){return await a(this,c,fe).call(this,e,ve)}async updateFile(e,t){return await a(this,c,xe).call(this,e,t)}async archiveFile(e){return await a(this,c,l).call(this,"DELETE",`${d}/${e}`)}async recoverFile(e){return await a(this,c,l).call(this,"PUT",`${d}/${e}/recover`)}async downloadFile(e,t){return await a(this,c,le).call(this,e,t)}async getFileVersionMetadata(e,t,s){const{withDraft:r}=s||{};return await a(this,c,l).call(this,"GET",`${d}/${encodeURIComponent(e)}/version/${encodeURIComponent(t)}/metadata`,{query:{...r&&{withDraft:"true"}}})}async updateFileVersionMetadata(e,t,s){return await a(this,c,l).call(this,"PUT",`${d}/${encodeURIComponent(e)}/version/${encodeURIComponent(t)}/metadata`,{body:JSON.stringify({metadata:s}),contentType:"application/json"})}async deleteFileVersionMetadata(e,t){return await a(this,c,l).call(this,"DELETE",`${d}/${encodeURIComponent(e)}/version/${encodeURIComponent(t)}/metadata`)}async getFileVersionMetadataBatch(e,t){const{withDraft:s}=t||{};return await a(this,c,te).call(this,e,async r=>(await a(this,c,l).call(this,"POST",`${d}/batch/version-metadata`,{body:JSON.stringify({entries:r,...s!==void 0&&{withDraft:s}}),contentType:"application/json"})).results)}async listFolders(e){const{archived:t,parentFolderId:s,projectId:r}=e||{};return await a(this,c,l).call(this,"GET",$,{query:{parentFolderId:s,archived:t,...r&&{projectId:r}}})}async getFolder(e){return await a(this,c,l).call(this,"GET",`${$}/${e}`)}async getFoldersBatch(e){return await a(this,c,te).call(this,e,async t=>(await a(this,c,l).call(this,"POST",`${d}/batch/folders`,{body:JSON.stringify({folderIds:t}),contentType:"application/json"})).results)}async createFolder(e,t,s){return await a(this,c,l).call(this,"POST",$,{body:JSON.stringify({name:e,...t&&{parentId:t},...s&&{projectId:s}}),contentType:"application/json"})}async updateFolder(e,t){const{name:s}=t;return await a(this,c,l).call(this,"PUT",`${$}/${e}`,{body:JSON.stringify({name:s}),contentType:"application/json"})}async archiveFolder(e){return await a(this,c,l).call(this,"DELETE",`${$}/${e}`)}async recoverFolder(e){return await a(this,c,l).call(this,"PUT",`${$}/${e}/recover`)}async downloadFolder(e){return await a(this,c,q).call(this,`${$}/${e}/download`)}async listComponents(e){const{folderId:t,ShowVersions:s,projectId:r}=e||{};return t?await a(this,c,l).call(this,"GET",`${$}/${t}/items`,{query:{itemType:ke,...s&&{ShowVersions:s}}}):await a(this,c,l).call(this,"GET",`${d}`,{query:{itemType:ke,...s&&{ShowVersions:s},...r&&{projectId:r}}})}async getComponent(e,t){return await a(this,c,Ie).call(this,e,t)}async createComponent(e){const{componentProps:t}=e;return await a(this,c,fe).call(this,e,ke,t)}async updateComponent(e,t){const{componentProps:s}=t;return await a(this,c,xe).call(this,e,t,s)}async downloadComponent(e,t){return await a(this,c,le).call(this,e,t)}async downloadComponentBundle(e,t){const{versionTag:s,withDraft:r}=t||{};return await a(this,c,q).call(this,`${d}/${e}/download/bundle`,{query:{...s&&{versionTag:s},...r&&{withDraft:r}}})}async archiveComponent(e){return await a(this,c,l).call(this,"DELETE",`${d}/${e}`)}async recoverComponent(e){return await a(this,c,l).call(this,"PUT",`${d}/${e}/recover`)}async getBuiltInComponent(e){return await(await a(this,c,q).call(this,`built-in/${e}/bundle`)).text()}async initBuiltInComponent(e,t,s){const r=await this.getBuiltInComponent(e.uuid),i=s??this.builtInGlobals??(typeof window<"u"?window.ThatOpenCompany:{})??{},o=Object.keys(i),h=o.map(g=>i[g]),m=new Function(...o,`${r}
2
- return main;`)(...h),y=(m==null?void 0:m.componentDefinition)??m;t.get(y)}async initBuiltInComponents(e,...t){await Promise.all(t.map(s=>this.initBuiltInComponent(s,e)))}async setup(e,...t){var o,h;const s=e.OBC,r=e.BUI;if(!(s!=null&&s.Components))throw new Error("globals.OBC must include Components");if(!(r!=null&&r.Manager))throw new Error("globals.BUI must include Manager");const i=new s.Components;return r.Manager.init(),this.setBuiltInGlobals(e),await this.initBuiltInComponents(i,...t),i.init(),(h=(o=this.context.appEventOrchestrator)==null?void 0:o.appLoaded)==null||h.call(o),{components:i}}throwError(e,t){var s,r;(r=(s=this.context.appEventOrchestrator)==null?void 0:s.appError)==null||r.call(s,e,t)}async listApps(e){const{folderId:t,ShowVersions:s,projectId:r}=e||{};return t?await a(this,c,l).call(this,"GET",`${$}/${t}/items`,{query:{itemType:Ae,...s&&{ShowVersions:s}}}):await a(this,c,l).call(this,"GET",`${d}`,{query:{itemType:Ae,...s&&{ShowVersions:s},...r&&{projectId:r}}})}async createApp(e){const{appProps:t}=e;return await a(this,c,fe).call(this,e,Ae,t)}async downloadApp(e,t){return await a(this,c,le).call(this,e,t)}async downloadAppBundle(e,t){const{versionTag:s,withDraft:r}=t||{};return await a(this,c,q).call(this,`${d}/${e}/download/bundle`,{query:{...s&&{versionTag:s},...r&&{withDraft:r}}})}async archiveApp(e){return await a(this,c,l).call(this,"DELETE",`${d}/${e}`)}async getNpmCredentials(){return await a(this,c,l).call(this,"GET",`${vs}/credentials`)}async executeComponent(e,t,s){if(this.localServerUrl){const r=`${this.localServerUrl}/api/${L}/${e}/execute`,i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!i.ok){const o=await i.text().catch(()=>"");throw new Error(`Local server request failed: ${i.status} - ${o}`)}return await i.json()}return await a(this,c,l).call(this,"POST",`${L}/${e}/execute`,{body:JSON.stringify(t),query:{...s&&{versionTag:s}},contentType:"application/json"})}async abortExecution(e){if(this.localServerUrl){const t=`${this.localServerUrl}/api/${L}/progress/${e}/abort`,s=await fetch(t,{method:"POST"});if(!s.ok){const r=await s.text().catch(()=>"");throw new Error(`Local server request failed: ${s.status} - ${r}`)}return await s.json()}return await a(this,c,l).call(this,"POST",`${L}/progress/${e}/abort`)}async listExecutions(e,t){if(this.localServerUrl){const s=t?`?projectId=${encodeURIComponent(t)}`:"",r=`${this.localServerUrl}/api/${L}/${e}/progress${s}`,i=await fetch(r);if(!i.ok){const o=await i.text().catch(()=>"");throw new Error(`Local server request failed: ${i.status} - ${o}`)}return await i.json()}return await a(this,c,l).call(this,"GET",`${L}/${e}/progress`,{query:{...t&&{projectId:t}}})}async getExecution(e){if(this.localServerUrl){const t=`${this.localServerUrl}/api/${L}/progress/${e}`,s=await fetch(t);if(!s.ok){const r=await s.text().catch(()=>"");throw new Error(`Local server request failed: ${s.status} - ${r}`)}return await s.json()}return await a(this,c,l).call(this,"GET",`${L}/progress/${e}`)}async onExecutionProgress(e,t){const s=this.localServerUrl?`${this.localServerUrl}?accessToken=${this.accessToken}`:this.wsUrl,r=await se(s,{...this.localServerUrl&&{transports:["websocket"]}});r.on("connect",function(){r.emit("executionSubscription",JSON.stringify({executionId:e})),r.on("execution",i=>{t(i)})}),r.on("connect_error",function(i){console.log(i)})}async createHiddenFile(e,t){const s=new FormData;return s.append("file",e),s.append("parentItemId",t),await a(this,c,l).call(this,"POST",`${d}/${B}`,{body:s})}async createHiddenFilesBatch(e,t){const s=new FormData;for(const r of e)s.append("files",r);return s.append("parentItemId",t),await a(this,c,l).call(this,"POST",`${d}/${B}/batch`,{body:s})}async deleteHiddenFile(e){return await a(this,c,l).call(this,"DELETE",`${d}/${B}/${e}`)}async getHiddenFile(e){return await a(this,c,l).call(this,"GET",`${d}/${B}/${e}`)}async downloadHiddenFile(e){return await a(this,c,q).call(this,`${d}/${B}/${e}/download`)}async getHiddenFileSignedUrl(e,t){return await a(this,c,l).call(this,"GET",`${d}/${B}/${e}/signed-url`,{...t!=null&&{query:{expiresIn:t}}})}async getHiddenFileSignedUrlsBatch(e,t){return await a(this,c,te).call(this,e,async s=>(await a(this,c,l).call(this,"POST",`${d}/${B}/signed-url/batch`,{body:JSON.stringify({hiddenFileIds:s,...t!=null&&{expiresIn:t}}),contentType:"application/json"})).results)}async getHiddenFilesByParent(e){return await a(this,c,l).call(this,"GET",`${d}/${e}/${B}`)}async deleteHiddenFilesByParent(e){return await a(this,c,l).call(this,"DELETE",`${d}/${e}/${B}`)}async uploadItemIcon(e,t){const s=new FormData;return s.append("icon",t),await a(this,c,l).call(this,"PUT",`${d}/${e}/icon`,{body:s})}async getItemIcon(e){return await a(this,c,q).call(this,`${d}/${e}/icon`)}async removeItemIcon(e){return await a(this,c,l).call(this,"DELETE",`${d}/${e}/icon`)}async updateItem(e,t){return await a(this,c,l).call(this,"PUT",`${d}/${e}`,{body:JSON.stringify(t),contentType:"application/json"})}async createVersion(e,t,s,r,i){const o=new FormData;return o.append("file",t),o.append("versionTag",s),r&&o.append("extraProps",JSON.stringify(r)),i&&o.append("metadata",JSON.stringify(i)),await a(this,c,l).call(this,"POST",`${d}/${e}/version`,{body:o})}async listVersions(e,t={}){return await a(this,c,l).call(this,"GET",`${d}/${encodeURIComponent(e)}/versions`,{query:t})}async listVersionsBatch(e,t={}){const{archived:s}=t;return await a(this,c,te).call(this,e,async r=>(await a(this,c,l).call(this,"POST",`${d}/batch/versions`,{body:JSON.stringify({itemIds:r,...s!==void 0&&{archived:s}}),contentType:"application/json"})).results)}async archiveVersion(e,t){return await a(this,c,l).call(this,"PUT",`${d}/${encodeURIComponent(e)}/version/${encodeURIComponent(t)}/archive`)}async recoverVersion(e,t){return await a(this,c,l).call(this,"PUT",`${d}/${encodeURIComponent(e)}/version/${encodeURIComponent(t)}/recover`)}async deleteVersion(e,t){return await a(this,c,l).call(this,"DELETE",`${d}/${encodeURIComponent(e)}/version/${encodeURIComponent(t)}`)}};c=new WeakSet,Be=function(e){return`${this.apiUrl}/${e}`},l=async function(e,t,s){const{body:r,query:i,contentType:o,retries:h,responseType:f,retryAttempt:m}=s||{},y=a(this,c,Be).call(this,t),g=a(this,c,mt).call(this,i),R=await this.resolveAccessToken(),At={...g,...this.useBearer?{}:{accessToken:R}};try{const O=await fetch(y+"?"+new URLSearchParams(At).toString(),{method:e,headers:{Accept:"application/json",...o&&{"Content-Type":o},...this.useBearer&&{Authorization:`Bearer ${R}`}},...r&&{body:r}});if(!O.ok){const j=await O.text().then(ie=>ie).catch(()=>"");throw new we(O.status,O.statusText,j,Os(O))}return f==="blob"?await O.blob():O.json().then(j=>j).catch(()=>{})}catch(O){const j=h??this.retries;if(j>0&&Cs(O)){const ie=m??0;return await Ss(Rs(O,ie)),await a(this,c,l).call(this,e,t,{...s,retries:j-1,retryAttempt:ie+1})}throw O}},q=async function(e,t){const{query:s}=t||{},r=a(this,c,Be).call(this,e),i=await this.resolveAccessToken(),o={...s,...this.useBearer?{}:{accessToken:i}};return await fetch(r+"?"+new URLSearchParams(o).toString(),{method:"GET",...this.useBearer&&{headers:{Authorization:`Bearer ${i}`}}})},te=async function(e,t){if(!e.length)return[];const s=[];for(let i=0;i<e.length;i+=Pe)s.push(e.slice(i,i+Pe));return(await Promise.all(s.map(t))).flat()},le=async function(e,t){const{versionTag:s,withDraft:r}=t||{};return await a(this,c,q).call(this,`${d}/${e}/download`,{query:{...s&&{versionTag:s},...r&&{withDraft:r}}})},fe=async function(e,t,s){const{name:r,versionTag:i,parentFolderId:o,projectId:h,file:f,metadata:m}=e,y=new FormData;return y.append("file",f),y.append("name",r),y.append("versionTag",i),y.append("itemType",t),o&&y.append("folderId",o),h&&y.append("projectId",h),s&&y.append("extraProps",JSON.stringify(s)),m&&y.append("metadata",JSON.stringify(m)),await a(this,c,l).call(this,"POST",d,{body:y})},xe=async function(e,t,s){const{name:r,versionTag:i,parentFolderId:o,file:h,metadata:f}=t;let m,y;if(h){const g=new FormData;g.append("file",h),i&&g.append("versionTag",i),s&&g.append("extraProps",JSON.stringify(s)),f&&g.append("metadata",JSON.stringify(f)),y=await a(this,c,l).call(this,"POST",`${d}/${e}/version`,{body:g})}if(r||o){const g={...r&&{name:r},...o&&{folderId:o}},R=JSON.stringify(g);m=await a(this,c,l).call(this,"PUT",`${d}/${e}`,{body:R,contentType:"application/json"})}return{item:m,version:y}},Ie=async function(e,t){const{showVersions:s=!1}=t||{};return await a(this,c,l).call(this,"GET",`${d}/${e}`,{query:{showVersions:s}})},mt=function(e){return e&&Object.entries(e).filter(([,t])=>t!==void 0).reduce((t,[s,r])=>(t[s]=r,t),{})};let ye=We;function gt(){if(typeof window>"u"||window.parent===window)throw new Error("client.channel only works inside a That Open app, which runs in an iframe of the platform.");return{post:n=>window.parent.postMessage(n,"*"),listen:n=>{const e=t=>{t.source===window.parent&&n(t.data)};return window.addEventListener("message",e),()=>window.removeEventListener("message",e)}}}const Le="channel:",$s=1e4;function de(n){try{n()}catch(e){console.error("[channel] a listener threw:",e)}}var x,k,A,Y,W,K,v,qe,Ue,G;class Ye{constructor(e,t){_(this,v);_(this,x,!1);_(this,k,[]);_(this,A,[]);_(this,Y,new Set);_(this,W,new Set);_(this,K,new Set);this.transport=e,this.controls=t}get joined(){return u(this,x)}get peers(){return u(this,k)}join(){return u(this,x)?Promise.resolve():a(this,v,qe).call(this,"joined",this.controls.join)}leave(){return!u(this,x)&&!u(this,A).some(e=>e.want==="joined")?Promise.resolve():a(this,v,qe).call(this,"left",this.controls.leave)}onChange(e){return u(this,Y).add(e),()=>void u(this,Y).delete(e)}onPeerJoined(e){return u(this,W).add(e),()=>void u(this,W).delete(e)}onPeerLeft(e){return u(this,K).add(e),()=>void u(this,K).delete(e)}applyJoined(){T(this,x,!0),a(this,v,Ue).call(this,"joined"),a(this,v,G).call(this)}applyLeft(){T(this,x,!1),T(this,k,[]),a(this,v,Ue).call(this,"left"),a(this,v,G).call(this)}applyPeers(e){T(this,k,e),a(this,v,G).call(this)}applyPeerJoined(e){!u(this,x)||u(this,k).some(t=>t.from===e.from)||(T(this,k,[...u(this,k),e]),u(this,W).forEach(t=>de(()=>t(e))),a(this,v,G).call(this))}applyPeerLeft(e){const t=u(this,k).find(s=>s.from===e);t&&(T(this,k,u(this,k).filter(s=>s.from!==e)),u(this,K).forEach(s=>de(()=>s(t))),a(this,v,G).call(this))}failPending(e){const t=u(this,A);return T(this,A,[]),t.forEach(s=>{clearTimeout(s.timer),s.reject(e)}),t.length>0}post(e){this.transport.post(e)}}x=new WeakMap,k=new WeakMap,A=new WeakMap,Y=new WeakMap,W=new WeakMap,K=new WeakMap,v=new WeakSet,qe=function(e,t){return new Promise((s,r)=>{const i={want:e,resolve:s,reject:r,timer:setTimeout(()=>{T(this,A,u(this,A).filter(o=>o!==i)),r(new Error(`The platform did not confirm ${e==="joined"?"joining":"leaving"} in time.`))},$s)};u(this,A).push(i),this.transport.post({type:"APP_CHANNEL_CONTROL",...t})})},Ue=function(e){const t=u(this,A).filter(s=>s.want===e);T(this,A,u(this,A).filter(s=>s.want!==e)),t.forEach(s=>{clearTimeout(s.timer),s.resolve()})},G=function(){u(this,Y).forEach(e=>de(e))};var X;class wt extends Ye{constructor(t){super(t,{join:{action:"joinCollab"},leave:{action:"leaveCollab"}});_(this,X,new Map)}on(t,s){const r=u(this,X).get(t)??new Set;return r.add(s),u(this,X).set(t,r),()=>void r.delete(s)}send(t,s){if(t.startsWith(Le))throw new Error(`Message types starting with '${Le}' are reserved.`);this.joined&&this.post({type:"APP_CHANNEL_PUBLISH",message:{type:t,payload:s}})}accepts(t){return t===void 0||t==="collab"}async handle(t){const s=u(this,X).get(t.type);if(!(s!=null&&s.size))return{handled:!1};const r=bt(t);return s.forEach(i=>de(()=>i(t.payload,r))),{handled:!0}}}X=new WeakMap;var U;class _t extends Ye{constructor(t,s){super(t,{join:{action:"joinExternal",kind:s},leave:{action:"leaveExternal",kind:s}});_(this,U,new Map);this.kind=s}on(t,s){if(u(this,U).has(t))throw new Error(`"${t}" already has a handler in this room. Remove it first.`);return u(this,U).set(t,s),()=>void u(this,U).delete(t)}accepts(t,s){return t!==void 0&&t!=="external"?!1:this.kind===void 0||t===void 0||this.kind===s}get hasHandlers(){return u(this,U).size>0}async handle(t){const s=u(this,U).get(t.type);if(!s)return{handled:!1};try{return{handled:!0,value:await s(t.payload,bt(t))}}catch(r){return{handled:!0,error:r instanceof Error?r.message:String(r)}}}}U=new WeakMap;function bt(n){return{from:n.from,at:n.at,requestId:n.requestId,kind:n.kind}}function Ns(n){const e=n;if((e==null?void 0:e.type)!=="THATOPEN_CHANNEL_MESSAGE")return null;const t=e.message;return!t||typeof t.type!="string"?null:{type:t.type,requestId:typeof t.requestId=="string"?t.requestId:void 0,payload:t.payload,at:typeof t.at=="number"?t.at:Date.now(),from:typeof t.from=="string"?t.from:"",scope:t.scope==="collab"||t.scope==="external"?t.scope:void 0,kind:typeof t.kind=="string"?t.kind:void 0}}var H,ne,I,D,F,b,De,pe,Et,vt,kt,Fe;class Tt{constructor(e){_(this,b);_(this,H);_(this,ne);_(this,I);_(this,D,new Map);_(this,F,new Set);T(this,H,e),T(this,ne,e.listen(t=>void a(this,b,Et).call(this,t)))}collab(){return u(this,I)??T(this,I,new wt(u(this,H))),u(this,I)}external(e){const t=e??"";let s=u(this,D).get(t);return s||(s=new _t(u(this,H),e),u(this,D).set(t,s)),s}dispose(){u(this,ne).call(this)}}H=new WeakMap,ne=new WeakMap,I=new WeakMap,D=new WeakMap,F=new WeakMap,b=new WeakSet,De=function(){return[...u(this,I)?[u(this,I)]:[],...u(this,D).values()]},pe=function(e,t){if(e==="collab")return u(this,I);if(e==="external")return u(this,D).get(typeof t=="string"?t:"")},Et=async function(e){const t=Ns(e);if(t){if(t.type.startsWith(Le)){a(this,b,vt).call(this,t);return}await a(this,b,kt).call(this,t)}},vt=function(e){var s,r,i;const t=e.payload??{};switch(e.type){case"channel:joined":(s=a(this,b,pe).call(this,t.scope,t.kind))==null||s.applyJoined();break;case"channel:left":(r=a(this,b,pe).call(this,t.scope,t.kind))==null||r.applyLeft();break;case"channel:peers":(i=a(this,b,pe).call(this,t.scope,t.kind))==null||i.applyPeers(t.peers??[]);break;case"channel:peer-joined":case"channel:peer-left":{if(!t.from)break;const o=t.scope==="collab"?[u(this,I)]:[...u(this,D).values()].filter(h=>h.accepts("external",t.kind));for(const h of o)e.type==="channel:peer-joined"?h==null||h.applyPeerJoined({from:t.from,kind:t.kind}):h==null||h.applyPeerLeft(t.from);break}case"channel:error":{const o=new Error(String(e.payload));a(this,b,De).call(this).map(f=>f.failPending(o)).some(Boolean)||console.error("[channel] error:",e.payload);break}}},kt=async function(e){const t=a(this,b,De).call(this).filter(i=>i.accepts(e.scope,e.kind));let s=!1;for(const i of t){const o=await i.handle(e);o.handled&&(s=!0,e.requestId&&a(this,b,Fe).call(this,e.requestId,o))}e.requestId&&e.scope==="external"&&t.length>0&&!s&&a(this,b,Fe).call(this,e.requestId,{handled:!0,error:`No handler for "${e.type}".`})},Fe=function(e,t){u(this,F).has(e)||(u(this,F).add(e),u(this,F).size>500&&u(this,F).delete(u(this,F).values().next().value),u(this,H).post({type:"APP_CHANNEL_PUBLISH",message:{type:t.error===void 0?"reply":"reply-error",requestId:e,payload:t.error===void 0?t.value:{error:t.error}}}))};const V="project",J="notifications";var z,re;const Ke=class Ke extends ye{constructor(t,s,r){super(typeof t=="string"?t:"",s,{...r,useBearer:!0});_(this,z);_(this,re);typeof t=="function"&&T(this,z,t)}async resolveAccessToken(){return u(this,z)?await u(this,z).call(this):super.resolveAccessToken()}static fromPlatformContext(t){const s=(typeof window<"u"?window.__THATOPEN_CONTEXT__:null)||{appId:"",projectId:"",accessToken:"",apiUrl:""},r=new Ke(s.accessToken,s.apiUrl,t);return r.context=s,r}get channel(){return u(this,re)??T(this,re,new Tt(gt())),u(this,re)}async getProject(t){return await this.request("GET",`${V}/${t}`)}async getProjectData(t){return await this.request("GET",`${V}/${t}/data`)}async getAvatar(t){return await this.request("GET",`account/${t}/avatar`,{responseType:"blob"})}async checkPermission(t){return await this.request("GET",`${V}/permissions/check`,{query:t})}async checkPermissionBatch(t){return(await this.request("POST",`${V}/permissions/check/batch`,{body:JSON.stringify({checks:t}),contentType:"application/json"})).results}async getNotifications(t){return await this.request("GET",J,{query:{...(t==null?void 0:t.cursor)!==void 0&&{cursor:t.cursor},...(t==null?void 0:t.limit)!==void 0&&{limit:String(t.limit)}}})}async getUnreadNotificationCount(){return(await this.request("GET",`${J}/unread-count`)).count}async markNotificationsRead(t){return await this.request("POST",`${J}/mark-read`,{body:JSON.stringify({ids:t}),contentType:"application/json"})}async markAllNotificationsRead(){return await this.request("POST",`${J}/mark-all-read`)}async getNotificationSubscriptions(){return await this.request("GET",`${J}/subscriptions`)}async unsubscribeFromAutomation(t){return await this.request("DELETE",`${J}/subscriptions/${t}`)}async subscribeToAutomation(t,s,r){return await this.request("POST",`${V}/${t}/events/hooks/${s}/subscription`,{body:JSON.stringify(r??{}),contentType:"application/json"})}async updateAutomationSubscription(t,s,r){return await this.request("PATCH",`${V}/${t}/events/hooks/${s}/subscription`,{body:JSON.stringify(r),contentType:"application/json"})}async onNotification(t){const s=await this.resolveAccessToken(),r=se(`${this.socketOrigin}/notifications?accessToken=${encodeURIComponent(s)}`,{transports:["websocket"]});return r.on("notification.created",i=>t({type:"created",id:i==null?void 0:i.id})),r.on("notification.read",i=>t({type:"read",id:i==null?void 0:i.id})),r.on("notifications.allRead",i=>t({type:"allRead",batch:i==null?void 0:i.batch})),()=>r.disconnect()}};z=new WeakMap,re=new WeakMap;let Me=Ke;const Ps={MAX_FIELDS:200,MAX_KEY_LENGTH:50,MAX_VALUE_LENGTH:50},Bs={uuid:"a3f82c1d-5b74-4e9a-bc30-d7e12f894a61"},xs={uuid:"2c9f4e8d-3a1b-4c5e-9d7f-0a2b6c8e1d3f"},Is={uuid:"b0b5e2a2-0b3a-4a6b-8b1c-0b1c4a6b8b1c"},Ls={uuid:"3f9c1a7e-6b2d-4e18-9a5c-7d0e2f4b6c81"},qs={uuid:"2c4ae432-fc24-43e9-9783-0c960c674e96"},Us={uuid:"6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f"},Ds={uuid:"69af63aa-19ba-4fc7-b17b-75647bac1d76"},Fs={uuid:"234f1416-528d-452a-9cc9-a16c5239b2eb"};exports.CDEManager=Bs;exports.ChannelClient=Tt;exports.ChannelRoom=Ye;exports.ClashesManager=xs;exports.CollabRoom=wt;exports.EngineServicesClient=ye;exports.ExternalRoom=_t;exports.FileList=Is;exports.GitHistoryManager=Ls;exports.HelloWorld=qs;exports.METADATA_LIMITS=Ps;exports.PlatformClient=Me;exports.ProjectManager=Us;exports.RequestError=we;exports.STORAGE_BATCH_MAX=Pe;exports.TopicsManager=Ds;exports.UIManager=Fs;exports.windowTransport=gt;
2
+ return main;`)(...h),y=(m==null?void 0:m.componentDefinition)??m;t.get(y)}async initBuiltInComponents(e,...t){await Promise.all(t.map(s=>this.initBuiltInComponent(s,e)))}async setup(e,...t){var o,h;const s=e.OBC,r=e.BUI;if(!(s!=null&&s.Components))throw new Error("globals.OBC must include Components");if(!(r!=null&&r.Manager))throw new Error("globals.BUI must include Manager");const i=new s.Components;return r.Manager.init(),this.setBuiltInGlobals(e),await this.initBuiltInComponents(i,...t),i.init(),(h=(o=this.context.appEventOrchestrator)==null?void 0:o.appLoaded)==null||h.call(o),{components:i}}throwError(e,t){var s,r;(r=(s=this.context.appEventOrchestrator)==null?void 0:s.appError)==null||r.call(s,e,t)}async listApps(e){const{folderId:t,ShowVersions:s,projectId:r}=e||{};return t?await a(this,c,l).call(this,"GET",`${$}/${t}/items`,{query:{itemType:Ae,...s&&{ShowVersions:s}}}):await a(this,c,l).call(this,"GET",`${d}`,{query:{itemType:Ae,...s&&{ShowVersions:s},...r&&{projectId:r}}})}async createApp(e){const{appProps:t}=e;return await a(this,c,fe).call(this,e,Ae,t)}async downloadApp(e,t){return await a(this,c,le).call(this,e,t)}async downloadAppBundle(e,t){const{versionTag:s,withDraft:r}=t||{};return await a(this,c,q).call(this,`${d}/${e}/download/bundle`,{query:{...s&&{versionTag:s},...r&&{withDraft:r}}})}async archiveApp(e){return await a(this,c,l).call(this,"DELETE",`${d}/${e}`)}async getNpmCredentials(){return await a(this,c,l).call(this,"GET",`${vs}/credentials`)}async executeComponent(e,t,s){if(this.localServerUrl){const r=`${this.localServerUrl}/api/${L}/${e}/execute`,i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!i.ok){const o=await i.text().catch(()=>"");throw new Error(`Local server request failed: ${i.status} - ${o}`)}return await i.json()}return await a(this,c,l).call(this,"POST",`${L}/${e}/execute`,{body:JSON.stringify(t),query:{...s&&{versionTag:s}},contentType:"application/json"})}async abortExecution(e){if(this.localServerUrl){const t=`${this.localServerUrl}/api/${L}/progress/${e}/abort`,s=await fetch(t,{method:"POST"});if(!s.ok){const r=await s.text().catch(()=>"");throw new Error(`Local server request failed: ${s.status} - ${r}`)}return await s.json()}return await a(this,c,l).call(this,"POST",`${L}/progress/${e}/abort`)}async listExecutions(e,t){if(this.localServerUrl){const s=t?`?projectId=${encodeURIComponent(t)}`:"",r=`${this.localServerUrl}/api/${L}/${e}/progress${s}`,i=await fetch(r);if(!i.ok){const o=await i.text().catch(()=>"");throw new Error(`Local server request failed: ${i.status} - ${o}`)}return await i.json()}return await a(this,c,l).call(this,"GET",`${L}/${e}/progress`,{query:{...t&&{projectId:t}}})}async getExecution(e){if(this.localServerUrl){const t=`${this.localServerUrl}/api/${L}/progress/${e}`,s=await fetch(t);if(!s.ok){const r=await s.text().catch(()=>"");throw new Error(`Local server request failed: ${s.status} - ${r}`)}return await s.json()}return await a(this,c,l).call(this,"GET",`${L}/progress/${e}`)}async onExecutionProgress(e,t){const s=this.localServerUrl?`${this.localServerUrl}?accessToken=${this.accessToken}`:this.wsUrl,r=await se(s,{...this.localServerUrl&&{transports:["websocket"]}});r.on("connect",function(){r.emit("executionSubscription",JSON.stringify({executionId:e})),r.on("execution",i=>{t(i)})}),r.on("connect_error",function(i){console.log(i)})}async createHiddenFile(e,t,s){const r=new FormData;return r.append("file",e),r.append("parentItemId",t),s!=null&&r.append("tag",s),await a(this,c,l).call(this,"POST",`${d}/${B}`,{body:r})}async createHiddenFilesBatch(e,t,s){const r=new FormData;for(const i of e)r.append("files",i);return r.append("parentItemId",t),s!=null&&r.append("tag",s),await a(this,c,l).call(this,"POST",`${d}/${B}/batch`,{body:r})}async deleteHiddenFile(e){return await a(this,c,l).call(this,"DELETE",`${d}/${B}/${e}`)}async getHiddenFile(e){return await a(this,c,l).call(this,"GET",`${d}/${B}/${e}`)}async downloadHiddenFile(e){return await a(this,c,q).call(this,`${d}/${B}/${e}/download`)}async getHiddenFileSignedUrl(e,t){return await a(this,c,l).call(this,"GET",`${d}/${B}/${e}/signed-url`,{...t!=null&&{query:{expiresIn:t}}})}async getHiddenFileSignedUrlsBatch(e,t){return await a(this,c,te).call(this,e,async s=>(await a(this,c,l).call(this,"POST",`${d}/${B}/signed-url/batch`,{body:JSON.stringify({hiddenFileIds:s,...t!=null&&{expiresIn:t}}),contentType:"application/json"})).results)}async getHiddenFilesByParent(e,t){return await a(this,c,l).call(this,"GET",`${d}/${e}/${B}`,{...t!=null&&{query:{tag:t}}})}async deleteHiddenFilesByParent(e){return await a(this,c,l).call(this,"DELETE",`${d}/${e}/${B}`)}async uploadItemIcon(e,t){const s=new FormData;return s.append("icon",t),await a(this,c,l).call(this,"PUT",`${d}/${e}/icon`,{body:s})}async getItemIcon(e){return await a(this,c,q).call(this,`${d}/${e}/icon`)}async removeItemIcon(e){return await a(this,c,l).call(this,"DELETE",`${d}/${e}/icon`)}async updateItem(e,t){return await a(this,c,l).call(this,"PUT",`${d}/${e}`,{body:JSON.stringify(t),contentType:"application/json"})}async createVersion(e,t,s,r,i){const o=new FormData;return o.append("file",t),o.append("versionTag",s),r&&o.append("extraProps",JSON.stringify(r)),i&&o.append("metadata",JSON.stringify(i)),await a(this,c,l).call(this,"POST",`${d}/${e}/version`,{body:o})}async listVersions(e,t={}){return await a(this,c,l).call(this,"GET",`${d}/${encodeURIComponent(e)}/versions`,{query:t})}async listVersionsBatch(e,t={}){const{archived:s}=t;return await a(this,c,te).call(this,e,async r=>(await a(this,c,l).call(this,"POST",`${d}/batch/versions`,{body:JSON.stringify({itemIds:r,...s!==void 0&&{archived:s}}),contentType:"application/json"})).results)}async archiveVersion(e,t){return await a(this,c,l).call(this,"PUT",`${d}/${encodeURIComponent(e)}/version/${encodeURIComponent(t)}/archive`)}async recoverVersion(e,t){return await a(this,c,l).call(this,"PUT",`${d}/${encodeURIComponent(e)}/version/${encodeURIComponent(t)}/recover`)}async deleteVersion(e,t){return await a(this,c,l).call(this,"DELETE",`${d}/${encodeURIComponent(e)}/version/${encodeURIComponent(t)}`)}};c=new WeakSet,Be=function(e){return`${this.apiUrl}/${e}`},l=async function(e,t,s){const{body:r,query:i,contentType:o,retries:h,responseType:f,retryAttempt:m}=s||{},y=a(this,c,Be).call(this,t),g=a(this,c,mt).call(this,i),R=await this.resolveAccessToken(),At={...g,...this.useBearer?{}:{accessToken:R}};try{const O=await fetch(y+"?"+new URLSearchParams(At).toString(),{method:e,headers:{Accept:"application/json",...o&&{"Content-Type":o},...this.useBearer&&{Authorization:`Bearer ${R}`}},...r&&{body:r}});if(!O.ok){const j=await O.text().then(ie=>ie).catch(()=>"");throw new we(O.status,O.statusText,j,Os(O))}return f==="blob"?await O.blob():O.json().then(j=>j).catch(()=>{})}catch(O){const j=h??this.retries;if(j>0&&Cs(O)){const ie=m??0;return await Ss(Rs(O,ie)),await a(this,c,l).call(this,e,t,{...s,retries:j-1,retryAttempt:ie+1})}throw O}},q=async function(e,t){const{query:s}=t||{},r=a(this,c,Be).call(this,e),i=await this.resolveAccessToken(),o={...s,...this.useBearer?{}:{accessToken:i}};return await fetch(r+"?"+new URLSearchParams(o).toString(),{method:"GET",...this.useBearer&&{headers:{Authorization:`Bearer ${i}`}}})},te=async function(e,t){if(!e.length)return[];const s=[];for(let i=0;i<e.length;i+=Pe)s.push(e.slice(i,i+Pe));return(await Promise.all(s.map(t))).flat()},le=async function(e,t){const{versionTag:s,withDraft:r}=t||{};return await a(this,c,q).call(this,`${d}/${e}/download`,{query:{...s&&{versionTag:s},...r&&{withDraft:r}}})},fe=async function(e,t,s){const{name:r,versionTag:i,parentFolderId:o,projectId:h,file:f,metadata:m}=e,y=new FormData;return y.append("file",f),y.append("name",r),y.append("versionTag",i),y.append("itemType",t),o&&y.append("folderId",o),h&&y.append("projectId",h),s&&y.append("extraProps",JSON.stringify(s)),m&&y.append("metadata",JSON.stringify(m)),await a(this,c,l).call(this,"POST",d,{body:y})},xe=async function(e,t,s){const{name:r,versionTag:i,parentFolderId:o,file:h,metadata:f}=t;let m,y;if(h){const g=new FormData;g.append("file",h),i&&g.append("versionTag",i),s&&g.append("extraProps",JSON.stringify(s)),f&&g.append("metadata",JSON.stringify(f)),y=await a(this,c,l).call(this,"POST",`${d}/${e}/version`,{body:g})}if(r||o){const g={...r&&{name:r},...o&&{folderId:o}},R=JSON.stringify(g);m=await a(this,c,l).call(this,"PUT",`${d}/${e}`,{body:R,contentType:"application/json"})}return{item:m,version:y}},Ie=async function(e,t){const{showVersions:s=!1}=t||{};return await a(this,c,l).call(this,"GET",`${d}/${e}`,{query:{showVersions:s}})},mt=function(e){return e&&Object.entries(e).filter(([,t])=>t!==void 0).reduce((t,[s,r])=>(t[s]=r,t),{})};let ye=We;function gt(){if(typeof window>"u"||window.parent===window)throw new Error("client.channel only works inside a That Open app, which runs in an iframe of the platform.");return{post:n=>window.parent.postMessage(n,"*"),listen:n=>{const e=t=>{t.source===window.parent&&n(t.data)};return window.addEventListener("message",e),()=>window.removeEventListener("message",e)}}}const Le="channel:",$s=1e4;function de(n){try{n()}catch(e){console.error("[channel] a listener threw:",e)}}var x,k,A,Y,W,K,v,qe,Ue,G;class Ye{constructor(e,t){_(this,v);_(this,x,!1);_(this,k,[]);_(this,A,[]);_(this,Y,new Set);_(this,W,new Set);_(this,K,new Set);this.transport=e,this.controls=t}get joined(){return u(this,x)}get peers(){return u(this,k)}join(){return u(this,x)?Promise.resolve():a(this,v,qe).call(this,"joined",this.controls.join)}leave(){return!u(this,x)&&!u(this,A).some(e=>e.want==="joined")?Promise.resolve():a(this,v,qe).call(this,"left",this.controls.leave)}onChange(e){return u(this,Y).add(e),()=>void u(this,Y).delete(e)}onPeerJoined(e){return u(this,W).add(e),()=>void u(this,W).delete(e)}onPeerLeft(e){return u(this,K).add(e),()=>void u(this,K).delete(e)}applyJoined(){T(this,x,!0),a(this,v,Ue).call(this,"joined"),a(this,v,G).call(this)}applyLeft(){T(this,x,!1),T(this,k,[]),a(this,v,Ue).call(this,"left"),a(this,v,G).call(this)}applyPeers(e){T(this,k,e),a(this,v,G).call(this)}applyPeerJoined(e){!u(this,x)||u(this,k).some(t=>t.from===e.from)||(T(this,k,[...u(this,k),e]),u(this,W).forEach(t=>de(()=>t(e))),a(this,v,G).call(this))}applyPeerLeft(e){const t=u(this,k).find(s=>s.from===e);t&&(T(this,k,u(this,k).filter(s=>s.from!==e)),u(this,K).forEach(s=>de(()=>s(t))),a(this,v,G).call(this))}failPending(e){const t=u(this,A);return T(this,A,[]),t.forEach(s=>{clearTimeout(s.timer),s.reject(e)}),t.length>0}post(e){this.transport.post(e)}}x=new WeakMap,k=new WeakMap,A=new WeakMap,Y=new WeakMap,W=new WeakMap,K=new WeakMap,v=new WeakSet,qe=function(e,t){return new Promise((s,r)=>{const i={want:e,resolve:s,reject:r,timer:setTimeout(()=>{T(this,A,u(this,A).filter(o=>o!==i)),r(new Error(`The platform did not confirm ${e==="joined"?"joining":"leaving"} in time.`))},$s)};u(this,A).push(i),this.transport.post({type:"APP_CHANNEL_CONTROL",...t})})},Ue=function(e){const t=u(this,A).filter(s=>s.want===e);T(this,A,u(this,A).filter(s=>s.want!==e)),t.forEach(s=>{clearTimeout(s.timer),s.resolve()})},G=function(){u(this,Y).forEach(e=>de(e))};var X;class wt extends Ye{constructor(t){super(t,{join:{action:"joinCollab"},leave:{action:"leaveCollab"}});_(this,X,new Map)}on(t,s){const r=u(this,X).get(t)??new Set;return r.add(s),u(this,X).set(t,r),()=>void r.delete(s)}send(t,s){if(t.startsWith(Le))throw new Error(`Message types starting with '${Le}' are reserved.`);this.joined&&this.post({type:"APP_CHANNEL_PUBLISH",message:{type:t,payload:s}})}accepts(t){return t===void 0||t==="collab"}async handle(t){const s=u(this,X).get(t.type);if(!(s!=null&&s.size))return{handled:!1};const r=bt(t);return s.forEach(i=>de(()=>i(t.payload,r))),{handled:!0}}}X=new WeakMap;var U;class _t extends Ye{constructor(t,s){super(t,{join:{action:"joinExternal",kind:s},leave:{action:"leaveExternal",kind:s}});_(this,U,new Map);this.kind=s}on(t,s){if(u(this,U).has(t))throw new Error(`"${t}" already has a handler in this room. Remove it first.`);return u(this,U).set(t,s),()=>void u(this,U).delete(t)}accepts(t,s){return t!==void 0&&t!=="external"?!1:this.kind===void 0||t===void 0||this.kind===s}get hasHandlers(){return u(this,U).size>0}async handle(t){const s=u(this,U).get(t.type);if(!s)return{handled:!1};try{return{handled:!0,value:await s(t.payload,bt(t))}}catch(r){return{handled:!0,error:r instanceof Error?r.message:String(r)}}}}U=new WeakMap;function bt(n){return{from:n.from,at:n.at,requestId:n.requestId,kind:n.kind}}function Ns(n){const e=n;if((e==null?void 0:e.type)!=="THATOPEN_CHANNEL_MESSAGE")return null;const t=e.message;return!t||typeof t.type!="string"?null:{type:t.type,requestId:typeof t.requestId=="string"?t.requestId:void 0,payload:t.payload,at:typeof t.at=="number"?t.at:Date.now(),from:typeof t.from=="string"?t.from:"",scope:t.scope==="collab"||t.scope==="external"?t.scope:void 0,kind:typeof t.kind=="string"?t.kind:void 0}}var H,ne,I,D,F,b,De,pe,Et,vt,kt,Fe;class Tt{constructor(e){_(this,b);_(this,H);_(this,ne);_(this,I);_(this,D,new Map);_(this,F,new Set);T(this,H,e),T(this,ne,e.listen(t=>void a(this,b,Et).call(this,t)))}collab(){return u(this,I)??T(this,I,new wt(u(this,H))),u(this,I)}external(e){const t=e??"";let s=u(this,D).get(t);return s||(s=new _t(u(this,H),e),u(this,D).set(t,s)),s}dispose(){u(this,ne).call(this)}}H=new WeakMap,ne=new WeakMap,I=new WeakMap,D=new WeakMap,F=new WeakMap,b=new WeakSet,De=function(){return[...u(this,I)?[u(this,I)]:[],...u(this,D).values()]},pe=function(e,t){if(e==="collab")return u(this,I);if(e==="external")return u(this,D).get(typeof t=="string"?t:"")},Et=async function(e){const t=Ns(e);if(t){if(t.type.startsWith(Le)){a(this,b,vt).call(this,t);return}await a(this,b,kt).call(this,t)}},vt=function(e){var s,r,i;const t=e.payload??{};switch(e.type){case"channel:joined":(s=a(this,b,pe).call(this,t.scope,t.kind))==null||s.applyJoined();break;case"channel:left":(r=a(this,b,pe).call(this,t.scope,t.kind))==null||r.applyLeft();break;case"channel:peers":(i=a(this,b,pe).call(this,t.scope,t.kind))==null||i.applyPeers(t.peers??[]);break;case"channel:peer-joined":case"channel:peer-left":{if(!t.from)break;const o=t.scope==="collab"?[u(this,I)]:[...u(this,D).values()].filter(h=>h.accepts("external",t.kind));for(const h of o)e.type==="channel:peer-joined"?h==null||h.applyPeerJoined({from:t.from,kind:t.kind}):h==null||h.applyPeerLeft(t.from);break}case"channel:error":{const o=new Error(String(e.payload));a(this,b,De).call(this).map(f=>f.failPending(o)).some(Boolean)||console.error("[channel] error:",e.payload);break}}},kt=async function(e){const t=a(this,b,De).call(this).filter(i=>i.accepts(e.scope,e.kind));let s=!1;for(const i of t){const o=await i.handle(e);o.handled&&(s=!0,e.requestId&&a(this,b,Fe).call(this,e.requestId,o))}e.requestId&&e.scope==="external"&&t.length>0&&!s&&a(this,b,Fe).call(this,e.requestId,{handled:!0,error:`No handler for "${e.type}".`})},Fe=function(e,t){u(this,F).has(e)||(u(this,F).add(e),u(this,F).size>500&&u(this,F).delete(u(this,F).values().next().value),u(this,H).post({type:"APP_CHANNEL_PUBLISH",message:{type:t.error===void 0?"reply":"reply-error",requestId:e,payload:t.error===void 0?t.value:{error:t.error}}}))};const V="project",J="notifications";var z,re;const Ke=class Ke extends ye{constructor(t,s,r){super(typeof t=="string"?t:"",s,{...r,useBearer:!0});_(this,z);_(this,re);typeof t=="function"&&T(this,z,t)}async resolveAccessToken(){return u(this,z)?await u(this,z).call(this):super.resolveAccessToken()}static fromPlatformContext(t){const s=(typeof window<"u"?window.__THATOPEN_CONTEXT__:null)||{appId:"",projectId:"",accessToken:"",apiUrl:""},r=new Ke(s.accessToken,s.apiUrl,t);return r.context=s,r}get channel(){return u(this,re)??T(this,re,new Tt(gt())),u(this,re)}async getProject(t){return await this.request("GET",`${V}/${t}`)}async getProjectData(t){return await this.request("GET",`${V}/${t}/data`)}async getAvatar(t){return await this.request("GET",`account/${t}/avatar`,{responseType:"blob"})}async checkPermission(t){return await this.request("GET",`${V}/permissions/check`,{query:t})}async checkPermissionBatch(t){return(await this.request("POST",`${V}/permissions/check/batch`,{body:JSON.stringify({checks:t}),contentType:"application/json"})).results}async getNotifications(t){return await this.request("GET",J,{query:{...(t==null?void 0:t.cursor)!==void 0&&{cursor:t.cursor},...(t==null?void 0:t.limit)!==void 0&&{limit:String(t.limit)}}})}async getUnreadNotificationCount(){return(await this.request("GET",`${J}/unread-count`)).count}async markNotificationsRead(t){return await this.request("POST",`${J}/mark-read`,{body:JSON.stringify({ids:t}),contentType:"application/json"})}async markAllNotificationsRead(){return await this.request("POST",`${J}/mark-all-read`)}async getNotificationSubscriptions(){return await this.request("GET",`${J}/subscriptions`)}async unsubscribeFromAutomation(t){return await this.request("DELETE",`${J}/subscriptions/${t}`)}async subscribeToAutomation(t,s,r){return await this.request("POST",`${V}/${t}/events/hooks/${s}/subscription`,{body:JSON.stringify(r??{}),contentType:"application/json"})}async updateAutomationSubscription(t,s,r){return await this.request("PATCH",`${V}/${t}/events/hooks/${s}/subscription`,{body:JSON.stringify(r),contentType:"application/json"})}async onNotification(t){const s=await this.resolveAccessToken(),r=se(`${this.socketOrigin}/notifications?accessToken=${encodeURIComponent(s)}`,{transports:["websocket"]});return r.on("notification.created",i=>t({type:"created",id:i==null?void 0:i.id})),r.on("notification.read",i=>t({type:"read",id:i==null?void 0:i.id})),r.on("notifications.allRead",i=>t({type:"allRead",batch:i==null?void 0:i.batch})),()=>r.disconnect()}};z=new WeakMap,re=new WeakMap;let Me=Ke;const Ps={MAX_FIELDS:200,MAX_KEY_LENGTH:50,MAX_VALUE_LENGTH:50},Bs={uuid:"a3f82c1d-5b74-4e9a-bc30-d7e12f894a61"},xs={uuid:"2c9f4e8d-3a1b-4c5e-9d7f-0a2b6c8e1d3f"},Is={uuid:"b0b5e2a2-0b3a-4a6b-8b1c-0b1c4a6b8b1c"},Ls={uuid:"3f9c1a7e-6b2d-4e18-9a5c-7d0e2f4b6c81"},qs={uuid:"2c4ae432-fc24-43e9-9783-0c960c674e96"},Us={uuid:"6f3a9c2e-8b1d-4e6a-9c3f-1d7b5a8e2c4f"},Ds={uuid:"69af63aa-19ba-4fc7-b17b-75647bac1d76"},Fs={uuid:"234f1416-528d-452a-9cc9-a16c5239b2eb"};exports.CDEManager=Bs;exports.ChannelClient=Tt;exports.ChannelRoom=Ye;exports.ClashesManager=xs;exports.CollabRoom=wt;exports.EngineServicesClient=ye;exports.ExternalRoom=_t;exports.FileList=Is;exports.GitHistoryManager=Ls;exports.HelloWorld=qs;exports.METADATA_LIMITS=Ps;exports.PlatformClient=Me;exports.ProjectManager=Us;exports.RequestError=we;exports.STORAGE_BATCH_MAX=Pe;exports.TopicsManager=Ds;exports.UIManager=Fs;exports.windowTransport=gt;
package/dist/index.es.js CHANGED
@@ -3089,12 +3089,15 @@ return main;`)(...h), y = (m == null ? void 0 : m.componentDefinition) ?? m;
3089
3089
  * Creates a hidden file attached to a parent item (e.g., dependencies, assets).
3090
3090
  * @param file - The file to upload.
3091
3091
  * @param parentFileId - The parent item's unique identifier.
3092
+ * @param tag - Optional label to tell hidden files of the same parent apart;
3093
+ * filter on it with {@link getHiddenFilesByParent}. Up to 50 characters:
3094
+ * letters, digits and `:._-`, starting with a letter or digit.
3092
3095
  * @returns The hidden file ID.
3093
3096
  */
3094
- async createHiddenFile(e, t) {
3095
- const s = new FormData();
3096
- return s.append("file", e), s.append("parentItemId", t), await a(this, c, l).call(this, "POST", `${d}/${B}`, {
3097
- body: s
3097
+ async createHiddenFile(e, t, s) {
3098
+ const r = new FormData();
3099
+ return r.append("file", e), r.append("parentItemId", t), s != null && r.append("tag", s), await a(this, c, l).call(this, "POST", `${d}/${B}`, {
3100
+ body: r
3098
3101
  });
3099
3102
  }
3100
3103
  /**
@@ -3103,14 +3106,16 @@ return main;`)(...h), y = (m == null ? void 0 : m.componentDefinition) ?? m;
3103
3106
  * (e.g. 3D Tiles); upload in chunks of up to 100 files per call.
3104
3107
  * @param files - The files to upload.
3105
3108
  * @param parentFileId - The parent item's unique identifier.
3109
+ * @param tag - Optional label, as in {@link createHiddenFile}. One tag
3110
+ * applies to every file in the batch.
3106
3111
  * @returns One result per uploaded file, in order, each with its hidden file ID.
3107
3112
  */
3108
- async createHiddenFilesBatch(e, t) {
3109
- const s = new FormData();
3110
- for (const r of e)
3111
- s.append("files", r);
3112
- return s.append("parentItemId", t), await a(this, c, l).call(this, "POST", `${d}/${B}/batch`, {
3113
- body: s
3113
+ async createHiddenFilesBatch(e, t, s) {
3114
+ const r = new FormData();
3115
+ for (const i of e)
3116
+ r.append("files", i);
3117
+ return r.append("parentItemId", t), s != null && r.append("tag", s), await a(this, c, l).call(this, "POST", `${d}/${B}/batch`, {
3118
+ body: r
3114
3119
  });
3115
3120
  }
3116
3121
  /**
@@ -3182,12 +3187,14 @@ return main;`)(...h), y = (m == null ? void 0 : m.componentDefinition) ?? m;
3182
3187
  })).results);
3183
3188
  }
3184
3189
  /**
3185
- * Lists all hidden files attached to a parent item.
3190
+ * Lists the hidden files attached to a parent item.
3186
3191
  * @param parentFileId - The parent item's unique identifier.
3192
+ * @param tag - Optional filter: only hidden files uploaded with this tag. A
3193
+ * tagged listing comes back in creation order.
3187
3194
  * @returns Array of hidden file entities.
3188
3195
  */
3189
- async getHiddenFilesByParent(e) {
3190
- return await a(this, c, l).call(this, "GET", `${d}/${e}/${B}`);
3196
+ async getHiddenFilesByParent(e, t) {
3197
+ return await a(this, c, l).call(this, "GET", `${d}/${e}/${B}`, { ...t != null && { query: { tag: t } } });
3191
3198
  }
3192
3199
  /**
3193
3200
  * Deletes all hidden files attached to a parent item.
@@ -6,6 +6,8 @@ export type HiddenFileEntity = {
6
6
  fileId: string;
7
7
  _id: ObjectId;
8
8
  parentItemId: ObjectId;
9
+ /** Label set on upload; absent on untagged files. */
10
+ tag?: string;
9
11
  };
10
12
  export type CreateHiddenItemResult = {
11
13
  hiddenFileId: string;
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "access": "public"
16
16
  },
17
17
  "private": false,
18
- "version": "0.16.1",
18
+ "version": "0.17.0",
19
19
  "main": "dist/index.cjs.js",
20
20
  "module": "dist/index.es.js",
21
21
  "types": "dist/index.d.ts",
@@ -149,28 +149,33 @@ document.body.style.margin = "0";
149
149
  gotcha below), then appended as the toolbar's light-DOM content:
150
150
 
151
151
  ```ts
152
+ import { html, render } from "lit";
153
+
152
154
  const headlessBar = document.createElement("top-viewer-toolbar");
153
155
  headlessBar.toggleAttribute("headless", true);
154
156
 
155
- const customButtons = document.createElement("bim-toolbar") as unknown as HTMLElement;
156
- customButtons.setAttribute("style", "pointer-events: auto;");
157
+ // A plain container — the `<bim-toolbar>` itself is rendered inside it.
158
+ const toolbarHost = document.createElement("div");
159
+ toolbarHost.style.pointerEvents = "auto";
157
160
  render(
158
161
  html`
159
- <bim-toolbar-section label-hidden style="background: transparent;">
160
- <top-viewer-mode-toggle-button></top-viewer-mode-toggle-button>
161
- <top-viewer-hide-button></top-viewer-hide-button>
162
- <top-viewer-select-button></top-viewer-select-button>
163
- </bim-toolbar-section>
164
- <bim-toolbar-section label-hidden style="background: transparent;">
165
- <bim-button
166
- icon="mdi:fit-to-page-outline"
167
- @click=${() => myOwnFitToViewLogic()}
168
- ><bim-tooltip placement="top">Zoom to fit</bim-tooltip></bim-button>
169
- </bim-toolbar-section>
162
+ <bim-toolbar>
163
+ <bim-toolbar-section label-hidden style="background: transparent;">
164
+ <top-viewer-mode-toggle-button></top-viewer-mode-toggle-button>
165
+ <top-viewer-hide-button></top-viewer-hide-button>
166
+ <top-viewer-select-button></top-viewer-select-button>
167
+ </bim-toolbar-section>
168
+ <bim-toolbar-section label-hidden style="background: transparent;">
169
+ <bim-button
170
+ icon="mdi:fit-to-page-outline"
171
+ @click=${() => myOwnFitToViewLogic()}
172
+ ><bim-tooltip placement="top">Zoom to fit</bim-tooltip></bim-button>
173
+ </bim-toolbar-section>
174
+ </bim-toolbar>
170
175
  `,
171
- customButtons,
176
+ toolbarHost,
172
177
  );
173
- headlessBar.appendChild(customButtons);
178
+ headlessBar.appendChild(toolbarHost);
174
179
  // headlessBar can now be appended anywhere inside <top-viewer>.
175
180
  ```
176
181
 
@@ -208,7 +213,7 @@ document.body.style.margin = "0";
208
213
  Custom Elements v1 forbids for elements created imperatively —
209
214
  `document.createElement("bim-button")` throws `NotSupportedError`.
210
215
  Render them with lit's `render(html\`...\`, container)` instead, exactly
211
- like the `customButtons` bar above — never build them by hand.
216
+ like the `toolbarHost` container above — never build them by hand.
212
217
  - **`bim-button` sizes itself** — square when it's icon-only, a consistent
213
218
  height when it has a label. Don't set `width`/`height`/`min-width`
214
219
  inline on it; that only fights its own layout and produces buttons that
@@ -225,7 +230,13 @@ document.body.style.margin = "0";
225
230
  ### 🧩 Standalone buttons reference
226
231
 
227
232
  Every button the default bar uses is independently importable/usable as
228
- its own custom element:
233
+ its own custom element. They render icon-only with a tooltip; set the
234
+ optional `label` attribute on any of them to show text next to the icon
235
+ (the tooltip stays as it is):
236
+
237
+ ```html
238
+ <top-viewer-hide-button label="Hide"></top-viewer-hide-button>
239
+ ```
229
240
 
230
241
  | Element | Does |
231
242
  |---|---|
@@ -237,16 +248,105 @@ document.body.style.margin = "0";
237
248
  | `<top-viewer-focus-button>` | Frames the camera on the target set |
238
249
  | `<top-viewer-reset-button>` | Restores full visibility + opacity (global) |
239
250
  | `<top-viewer-select-button>` | Activates the default Select tool |
240
- | `<top-viewer-clip-button>` | Activates the Clip tool |
251
+ | `<top-viewer-clip-button>` | Clipping planes: face-placing mode by default, or axis planes / a mode menu via `modes` (see below) |
241
252
  | `<top-viewer-measure-length-button>` | Activates length measurement |
242
253
  | `<top-viewer-measure-area-button>` | Activates area measurement |
243
254
  | `<top-viewer-measure-angle-button>` | Activates angle measurement |
244
255
  | `<top-viewer-measure-edge-button>` | Activates edge measurement |
245
256
  | `<top-viewer-measure-face-button>` | Activates face measurement |
246
257
  | `<top-viewer-measure-volume-button>` | Activates volume measurement |
258
+ | `<top-viewer-measure-button>` | All measurement modes in one button (a menu by default), or a chosen subset via `modes` (see below) |
247
259
  | `<top-viewer-projection-toggle-button>` | Toggles Perspective ⇄ Orthographic |
248
260
  | `<top-viewer-walkthrough-button>` | Toggles first-person walkthrough |
261
+ | `<top-viewer-navigation-button>` | Switches between orbit and first-person navigation (a menu by default), or a single chosen mode via `modes` (see below) |
249
262
 
250
263
  Each one self-wires from context — drop it anywhere under `<top-viewer>`
251
264
  and it works, with no props to pass in.
265
+
266
+ ### ✂️ Clip button modes
267
+
268
+ Without any attribute, `<top-viewer-clip-button>` enters face-placing mode:
269
+ double-click a face in the model and a clip plane is dropped on it. The
270
+ optional `modes` attribute changes what the button offers — a whitespace-
271
+ (or comma-) separated list of `x`, `y`, `z` and `face` (case-insensitive;
272
+ unknown tokens are ignored, duplicates dropped, the order you write is the
273
+ order shown):
274
+
275
+ ```html
276
+ <!-- a menu with four entries: X axis, Y axis, Z axis, Face -->
277
+ <top-viewer-clip-button modes="x y z face"></top-viewer-clip-button>
278
+
279
+ <!-- one mode = no menu; a click creates a horizontal cut right away -->
280
+ <top-viewer-clip-button modes="y"></top-viewer-clip-button>
281
+
282
+ <!-- default: face-placing mode -->
283
+ <top-viewer-clip-button></top-viewer-clip-button>
284
+ ```
285
+
286
+ - **One mode** — the button runs it directly on click. `face` is the
287
+ default face-placing behavior.
288
+ - **Two or more** — clicking opens a menu with one entry per mode ("X
289
+ axis", "Y axis", "Z axis", "Face"); picking one runs it and closes the
290
+ menu.
291
+ - **Axis modes** create a single plane through the center of the bounding
292
+ box of all loaded models (nothing happens if no model is loaded). Axes
293
+ follow the three.js convention — **Y is vertical**, so `y` is a
294
+ horizontal cut. The plane's normal is the *negative* axis — `(-1, 0, 0)`,
295
+ `(0, -1, 0)`, `(0, 0, -1)` — so the plane clips what lies on the
296
+ positive side of the axis (`y` removes everything above the middle of
297
+ the model). Axis planes behave exactly like face-placed ones: same
298
+ section styling, listed in the objects outliner, draggable by their
299
+ gizmo, removable with Delete.
300
+ - The button shows as active only while face-placing mode is on.
301
+
302
+ ### 📏 Measure button modes
303
+
304
+ `<top-viewer-measure-button>` puts the measurement tools behind a single
305
+ button. Without any attribute it offers all six modes — `length`, `area`,
306
+ `angle`, `edge`, `face`, `volume` — in a menu. The optional `modes`
307
+ attribute picks a subset (whitespace- or comma-separated, case-insensitive;
308
+ unknown tokens are ignored, duplicates dropped, your order is kept):
309
+
310
+ ```html
311
+ <!-- default: a menu with all six modes -->
312
+ <top-viewer-measure-button></top-viewer-measure-button>
313
+
314
+ <!-- a menu with just these three, in this order -->
315
+ <top-viewer-measure-button modes="length area volume"></top-viewer-measure-button>
316
+
317
+ <!-- one mode = no menu; a click starts that measurement right away -->
318
+ <top-viewer-measure-button modes="length"></top-viewer-measure-button>
319
+ ```
320
+
321
+ - **One mode** — a click activates it directly, exactly like the matching
322
+ standalone button (`length` and `area` measure freely; `edge` and `face`
323
+ snap to edges and faces).
324
+ - **Two or more** — a click opens a menu with one text-labelled entry per
325
+ mode ("Length", "Area", "Angle", "Edge", "Face", "Volume"); picking one
326
+ activates it and closes the menu.
327
+ - The button shows as active while any of its modes is the active
328
+ measurement mode, and its icon switches to that mode's icon (a ruler
329
+ otherwise). In the menu, the active mode's entry is marked.
330
+
331
+ ### 🧭 Navigation button modes
332
+
333
+ `<top-viewer-navigation-button>` switches how the camera moves. Without any
334
+ attribute it offers both modes — `orbit` and `first-person` — in a menu.
335
+ The optional `modes` attribute narrows or reorders them (whitespace- or
336
+ comma-separated, case-insensitive; unknown tokens are ignored, duplicates
337
+ dropped, your order is kept):
338
+
339
+ ```html
340
+ <!-- default: a menu with "Orbit" and "First person" -->
341
+ <top-viewer-navigation-button></top-viewer-navigation-button>
342
+
343
+ <!-- one mode = no menu; a click switches straight to it -->
344
+ <top-viewer-navigation-button modes="orbit"></top-viewer-navigation-button>
345
+ ```
346
+
347
+ - `orbit` turns first-person navigation off (nothing happens if it already
348
+ is); `first-person` turns it on (nothing happens if it already is) — the
349
+ same first-person navigation `<top-viewer-walkthrough-button>` toggles.
350
+ - The button's icon always shows the current mode, and the button is active
351
+ while first-person is on. In the menu, the current mode's entry is marked.
252
352
  */
@@ -39,6 +39,13 @@ async function main() {
39
39
  const hidden2 = await client.createHiddenFile(hiddenBlob2, parentId);
40
40
  console.log(`Created hidden file 2: [${hidden2.hiddenFileId}]`);
41
41
 
42
+ // --- Tags ---
43
+ // The tag is optional on upload; a batch upload applies one tag to every file in it.
44
+ // Filtering by tag returns that tag's files in creation order.
45
+ const tagged = await client.createHiddenFile(hiddenBlob1, parentId, 'example:tagged');
46
+ const taggedList = await client.getHiddenFilesByParent(parentId, 'example:tagged');
47
+ console.log(`\nHidden files tagged 'example:tagged': ${taggedList.length} (first: [${tagged.hiddenFileId}] tag=${taggedList[0]?.tag})`);
48
+
42
49
  // --- Get ---
43
50
  const fetched = await client.getHiddenFile(hidden1.hiddenFileId);
44
51
  console.log(`\nHidden file 1 detail:`);