SceneService.js 11 KB

12345
  1. /*
  2. All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. See https://js.arcgis.com/4.25/esri/copyright.txt for details.
  4. */
  5. import{_ as e}from"../../chunks/tslib.es6.js";import t from"../../request.js";import r from"../../core/Error.js";import"../../core/has.js";import o from"../../core/Logger.js";import{isSome as i}from"../../core/maybe.js";import{debounce as s}from"../../core/promiseUtils.js";import{urlToObject as a}from"../../core/urlUtils.js";import{property as n}from"../../core/accessorSupport/decorators/property.js";import"../../core/arrayUtils.js";import"../../core/accessorSupport/ensureType.js";import{reader as l}from"../../core/accessorSupport/decorators/reader.js";import{subclass as p}from"../../core/accessorSupport/decorators/subclass.js";import{writer as d}from"../../core/accessorSupport/decorators/writer.js";import{updateOrigins as c}from"../../core/accessorSupport/originUtils.js";import u from"../../geometry/Extent.js";import m from"../../geometry/HeightModelInfo.js";import y from"../../geometry/SpatialReference.js";import{titleFromUrlAndName as h,parse as f,cleanTitle as v,sanitizeUrlWithLayerId as S,writeUrlWithLayerId as g}from"../support/arcgisLayerUrl.js";import{id as w,url as I}from"../support/commonProperties.js";import{fetchIndexInfo as x}from"../support/I3SIndexInfo.js";import b from"../../portal/Portal.js";import j from"../../portal/PortalItem.js";import{saveResources as _}from"../../webdoc/support/saveUtils.js";const R="esri.layers.mixins.SceneService",A=o.getLogger(R),N=o=>{let N=class extends o{constructor(){super(...arguments),this.spatialReference=null,this.fullExtent=null,this.heightModelInfo=null,this.minScale=0,this.maxScale=0,this.version={major:Number.NaN,minor:Number.NaN,versionString:""},this.copyright=null,this.sublayerTitleMode="item-title",this.title=null,this.layerId=null,this.indexInfo=null,this._debouncedSaveOperations=s((async(e,t,r)=>{switch(e){case L.SAVE:return this._save(t);case L.SAVE_AS:return this._saveAs(r,t)}}))}readSpatialReference(e,t){return this._readSpatialReference(t)}_readSpatialReference(e){if(null!=e.spatialReference)return y.fromJSON(e.spatialReference);{const t=e.store,r=t.indexCRS||t.geographicCRS,o=r&&parseInt(r.substring(r.lastIndexOf("/")+1,r.length),10);return null!=o?new y(o):null}}readFullExtent(e,t,r){if(null!=e&&"object"==typeof e){const o=null==e.spatialReference?{...e,spatialReference:this._readSpatialReference(t)}:e;return u.fromJSON(o,r)}const o=t.store,i=this._readSpatialReference(t);return null==i||null==o||null==o.extent||!Array.isArray(o.extent)||o.extent.some((e=>e<U))?null:new u({xmin:o.extent[0],ymin:o.extent[1],xmax:o.extent[2],ymax:o.extent[3],spatialReference:i})}parseVersionString(e){const t={major:Number.NaN,minor:Number.NaN,versionString:e},r=e.split(".");return r.length>=2&&(t.major=parseInt(r[0],10),t.minor=parseInt(r[1],10)),t}readVersion(e,t){const r=t.store,o=null!=r.version?r.version.toString():"";return this.parseVersionString(o)}readTitlePortalItem(e){return"item-title"!==this.sublayerTitleMode?void 0:e}readTitleService(e,t){const r=this.portalItem&&this.portalItem.title;if("item-title"===this.sublayerTitleMode)return h(this.url,t.name);let o=t.name;if(!o&&this.url){const e=f(this.url);i(e)&&(o=e.title)}return"item-title-and-service-name"===this.sublayerTitleMode&&r&&(o=r+" - "+o),v(o)}set url(e){const t=S({layer:this,url:e,nonStandardUrlAllowed:!1,logger:A});this._set("url",t.url),null!=t.layerId&&this._set("layerId",t.layerId)}writeUrl(e,t,r,o){g(this,e,"layers",t,o)}get parsedUrl(){const e=this._get("url"),t=a(e);return null!=this.layerId&&(t.path=`${t.path}/layers/${this.layerId}`),t}async _fetchIndexAndUpdateExtent(e,t){this.indexInfo=x(this.parsedUrl.path,this.rootNode,e,this.apiKey,A,t),null==this.fullExtent||this.fullExtent.hasZ||this._updateExtent(await this.indexInfo)}_updateExtent(e){if("page"===e?.type){const t=e.rootIndex%e.pageSize,o=e.rootPage?.nodes?.[t];if(null==o||null==o.obb||null==o.obb.center||null==o.obb.halfSize)throw new r("sceneservice:invalid-node-page","Invalid node page.");if(o.obb.center[0]<U||null==this.fullExtent||this.fullExtent.hasZ)return;const i=o.obb.halfSize,s=o.obb.center[2],a=Math.sqrt(i[0]*i[0]+i[1]*i[1]+i[2]*i[2]);this.fullExtent.zmin=s-a,this.fullExtent.zmax=s+a}else if("node"===e?.type){const t=e.rootNode?.mbs;if(!Array.isArray(t)||4!==t.length||t[0]<U)return;const r=t[2],o=t[3],{fullExtent:i}=this;i&&(i.zmin=r-o,i.zmax=r+o)}}async _fetchService(e){if(null==this.url)throw new r("sceneservice:url-not-set","Scene service can not be loaded without valid portal item or url");if(null==this.layerId&&/SceneServer\/*$/i.test(this.url)){const t=await this._fetchFirstLayerId(e);null!=t&&(this.layerId=t)}return this._fetchServiceLayer(e)}async _fetchFirstLayerId(e){const r=await t(this.url,{query:{f:"json",token:this.apiKey},responseType:"json",signal:e});if(r.data&&Array.isArray(r.data.layers)&&r.data.layers.length>0)return r.data.layers[0].id}async _fetchServiceLayer(e){const r=await t(this.parsedUrl?.path??"",{query:{f:"json",token:this.apiKey},responseType:"json",signal:e});r.ssl&&(this.url=this.url.replace(/^http:/i,"https:"));let o=!1;if(r.data.layerType&&"Voxel"===r.data.layerType&&(o=!0),o)return this._fetchVoxelServiceLayer();const i=r.data;this.read(i,{origin:"service",url:this.parsedUrl}),this.validateLayer(i)}async _fetchVoxelServiceLayer(e){const r=(await t(this.parsedUrl?.path+"/layer",{query:{f:"json",token:this.apiKey},responseType:"json",signal:e})).data;this.read(r,{origin:"service",url:this.parsedUrl}),this.validateLayer(r)}async _ensureLoadBeforeSave(){await this.load(),"beforeSave"in this&&"function"==typeof this.beforeSave&&await this.beforeSave()}validateLayer(e){}_updateTypeKeywords(e,t,r){e.typeKeywords||(e.typeKeywords=[]);const o=t.getTypeKeywords();for(const i of o)e.typeKeywords.push(i);e.typeKeywords&&(e.typeKeywords=e.typeKeywords.filter(((e,t,r)=>r.indexOf(e)===t)),r===T.newItem&&(e.typeKeywords=e.typeKeywords.filter((e=>"Hosted Service"!==e))))}async _saveAs(e,t){const o={...K,...t};let i=j.from(e);i||(A.error("_saveAs(): requires a portal item parameter"),await Promise.reject(new r("sceneservice:portal-item-required","_saveAs() requires a portal item to save to"))),i.id&&(i=i.clone(),i.id=null);const s=i.portal||b.getDefault();await this._ensureLoadBeforeSave(),i.type=O,i.portal=s;const a={origin:"portal-item",url:null,messages:[],portal:s,portalItem:i,writtenProperties:[],blockedRelativeUrls:[],resources:{toAdd:[],toUpdate:[],toKeep:[],pendingOperations:[]}},n={layers:[this.write({},a)]};return await Promise.all(a.resources?.pendingOperations??[]),await this._validateAgainstJSONSchema(n,a,o),i.url=this.url,i.title||(i.title=this.title),this._updateTypeKeywords(i,o,T.newItem),await s._signIn(),await(s.user?.addItem({item:i,folder:o&&o.folder,data:n})),await _(this.resourceReferences,a,null),this.portalItem=i,c(a),a.portalItem=i,i}async _save(e){const t={...K,...e};if(!this.portalItem)throw A.error("_save(): requires the .portalItem property to be set"),new r("sceneservice:portal-item-not-set","Portal item to save to has not been set on this SceneService");if(this.portalItem.type!==O)throw A.error("_save(): Non-matching portal item type. Got "+this.portalItem.type+", expected "+O),new r("sceneservice:portal-item-wrong-type",`Portal item needs to have type "${O}"`);await this._ensureLoadBeforeSave();const o={origin:"portal-item",url:this.portalItem.itemUrl&&a(this.portalItem.itemUrl),messages:[],portal:this.portalItem.portal||b.getDefault(),portalItem:this.portalItem,writtenProperties:[],blockedRelativeUrls:[],resources:{toAdd:[],toUpdate:[],toKeep:[],pendingOperations:[]}},i={layers:[this.write({},o)]};return await Promise.all(o.resources?.pendingOperations??[]),await this._validateAgainstJSONSchema(i,o,t),this.portalItem.url=this.url,this.portalItem.title||(this.portalItem.title=this.title),this._updateTypeKeywords(this.portalItem,t,T.existingItem),await this.portalItem.update({data:i}),await _(this.resourceReferences,o,null),c(o),this.portalItem}async _validateAgainstJSONSchema(e,t,o){let i=t.messages?.filter((e=>"error"===e.type)).map((e=>new r(e.name,e.message,e.details)))??[];if(o&&o.validationOptions?.ignoreUnsupported&&(i=i.filter((e=>"layer:unsupported"!==e.name&&"symbol:unsupported"!==e.name&&"symbol-layer:unsupported"!==e.name&&"property:unsupported"!==e.name&&"url:unsupported"!==e.name&&"scenemodification:unsupported"!==e.name))),o.validationOptions?.enabled||E){const t=(await import("../support/schemaValidator.js")).validate(e,o.portalItemLayerType);if(t.length>0){const e=`Layer item did not validate:\n${t.join("\n")}`;if(A.error(`_validateAgainstJSONSchema(): ${e}`),"throw"===o.validationOptions?.failPolicy){const e=t.map((e=>new r("sceneservice:schema-validation",e))).concat(i);throw new r("sceneservice-validate:error","Failed to save layer item due to schema validation, see `details.errors`.",{combined:e})}}}if(i.length>0)throw new r("sceneservice:save","Failed to save SceneService due to unsupported or invalid content. See 'details.errors' for more detailed information",{errors:i})}};return e([n(w)],N.prototype,"id",void 0),e([n({type:y})],N.prototype,"spatialReference",void 0),e([l("spatialReference",["spatialReference","store.indexCRS","store.geographicCRS"])],N.prototype,"readSpatialReference",null),e([n({type:u})],N.prototype,"fullExtent",void 0),e([l("fullExtent",["fullExtent","store.extent","spatialReference","store.indexCRS","store.geographicCRS"])],N.prototype,"readFullExtent",null),e([n({readOnly:!0,type:m})],N.prototype,"heightModelInfo",void 0),e([n({type:Number,json:{name:"layerDefinition.minScale",write:!0,origins:{service:{read:{source:"minScale"},write:!1}}}})],N.prototype,"minScale",void 0),e([n({type:Number,json:{name:"layerDefinition.maxScale",write:!0,origins:{service:{read:{source:"maxScale"},write:!1}}}})],N.prototype,"maxScale",void 0),e([n({readOnly:!0})],N.prototype,"version",void 0),e([l("version",["store.version"])],N.prototype,"readVersion",null),e([n({type:String,json:{read:{source:"copyrightText"}}})],N.prototype,"copyright",void 0),e([n({type:String,json:{read:!1}})],N.prototype,"sublayerTitleMode",void 0),e([n({type:String})],N.prototype,"title",void 0),e([l("portal-item","title")],N.prototype,"readTitlePortalItem",null),e([l("service","title",["name"])],N.prototype,"readTitleService",null),e([n({type:Number,json:{origins:{service:{read:{source:"id"}},"portal-item":{write:{target:"id",isRequired:!0,ignoreOrigin:!0},read:!1}}}})],N.prototype,"layerId",void 0),e([n(I)],N.prototype,"url",null),e([d("url")],N.prototype,"writeUrl",null),e([n()],N.prototype,"parsedUrl",null),e([n({readOnly:!0})],N.prototype,"store",void 0),e([n({type:String,readOnly:!0,json:{read:{source:"store.rootNode"}}})],N.prototype,"rootNode",void 0),N=e([p(R)],N),N},U=-1e38,E=!1;var T;!function(e){e[e.existingItem=0]="existingItem",e[e.newItem=1]="newItem"}(T||(T={}));const O="Scene Service",K={getTypeKeywords:()=>[],portalItemLayerType:"unknown",validationOptions:{enabled:!0,ignoreUnsupported:!1,failPolicy:"throw"}};var L;!function(e){e[e.SAVE=0]="SAVE",e[e.SAVE_AS=1]="SAVE_AS"}(L||(L={}));export{O as SCENE_SERVICE_ITEM_TYPE,L as SaveOperationType,N as SceneService};