@hology/core 0.0.49 → 0.0.51

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.
@@ -1,4 +1,4 @@
1
- import e from"typedi";import{loadScene as t}from"../scene/bootstrap.js";import{ActorFactory as n}from"./actors/factory.js";import{World as s}from"./services/world.js";import{ViewController as o}from"./services/render.js";import{RenderingView as r}from"../rendering.js";import{PhysicsSystem as i}from"./services/physics/physics-system.js";import{MeshComponent as a}from"./actors/builtin/components/mesh-component.js";import{activeContainerInstance as c}from"./actors/internal/container-map.js";import{InputService as m}from"./input/index.js";import{RuntimeAssetsService as l}from"../scene/runtime-asset-service.js";import{AssetResourceLoader as d}from"../scene/asset-resource-loader.js";import{AssetLoader as p}from"./services/asset-loader.js";import{polyfillClient as h}from"./polyfill.js";import{Subject as u}from"rxjs";import{PointerEvents as f}from"./services/pointer-events.js";import{RuntimeBundledBackendService as g}from"../scene/runtime-bundled-backend-service.js";export function initiateGame(m,u){if(h(),0!=u.element.childNodes.length)return console.error("Can not initialize the game with a non-empty html element"),null;e.has(o);const w=e.of("default"),j=new HologyRuntime(w),v=new n(w,{inEditor:!1});var S;e.set(n,v),S=u.element,Object.assign(S.style,{position:"absolute",top:"0",left:"0",width:"100%",height:"100%"});const y=new r(u.element,{enableXR:!0===u.xr?.enabled,maxPixelRatio:u.rendering?.maxPixelRatio});y.renderer.shadowMap.autoUpdate=!0,null!=u?.rendering?.resolutionScale&&(y.resolutionScale=u.rendering.resolutionScale),e.set(r,y);const I=new o(y);e.set(o,I);const x=e.get(s);e.set(s,x);const b=new g,D=new l(b),R=new d;R.setDataDir(u.dataDir);const G=Object.entries(u.shaders).map((([e,t])=>({name:e,type:t}))),H=new p(R,D,G);return e.set(p,H),(async()=>{await b.preloadData();const n=e.get(i);if(await n.start(),j.isShutdown)return;const{scene:s,actors:o}=await t(y,u.sceneName,u.dataDir,u.shaders,u.actors,v,b,D,R);if(x.scene=s,j.isShutdown)return void y.stop();e.import([a]);for(const e of o)x.addActor(e);n.addFromScene(s),y.loop((e=>{})),j.status=5,c.value=w,w.remove(m),w.set({id:m,type:m});const r=w.get(m);c.value=null,j.gameInstance=r,w.get(f).start(),r instanceof GameInstance&&r.onStart(),j._resolver(!0)})(),j}export class GameInstance{onStart(){}onShutdown(){}}export function createHologyScene(){}export class HologyRuntime{constructor(e){this.containerInstance=e,this.status=0,this.isShutdown=!1,this.shutdownStarted=new u,this.ready=new Promise((e=>{this._resolver=e}))}getWorld(){return this.containerInstance.get(s)}getService(e){return this.containerInstance.get(e)}shutdown(){this.isShutdown=!0,this.shutdownStarted.next(),this.gameInstance instanceof GameInstance&&this.gameInstance.onShutdown(),this.containerInstance.get(m).stop();const e=this.containerInstance.get(r);e?.stop();for(const e of this.getWorld().actors)this.getWorld().removeActor(e);this.containerInstance.get(i).stop(),this.containerInstance.get(f).stop(),this.containerInstance.reset()}}
1
+ import e from"typedi";import{loadScene as t}from"../scene/bootstrap.js";import{ActorFactory as n}from"./actors/factory.js";import{World as s}from"./services/world.js";import{ViewController as o}from"./services/render.js";import{RenderingView as r}from"../rendering.js";import{PhysicsSystem as i}from"./services/physics/physics-system.js";import{MeshComponent as a}from"./actors/builtin/components/mesh-component.js";import{activeContainerInstance as c}from"./actors/internal/container-map.js";import{InputService as m}from"./input/index.js";import{RuntimeAssetsService as l}from"../scene/runtime-asset-service.js";import{AssetResourceLoader as d}from"../scene/asset-resource-loader.js";import{AssetLoader as p}from"./services/asset-loader.js";import{polyfillClient as h}from"./polyfill.js";import{Subject as u}from"rxjs";import{PointerEvents as f}from"./services/pointer-events.js";import{RuntimeBundledBackendService as g}from"../scene/runtime-bundled-backend-service.js";export function initiateGame(m,u){if(h(),0!=u.element.childNodes.length)return console.error("Can not initialize the game with a non-empty html element"),null;e.has(o);const w=e.of("default"),j=new HologyRuntime(w),v=new n(w,{inEditor:!1});var S;e.set(n,v),S=u.element,Object.assign(S.style,{position:"absolute",top:"0",left:"0",width:"100%",height:"100%"});const y=new r(u.element,{enableXR:!0===u.xr?.enabled,maxPixelRatio:u.rendering?.maxPixelRatio});y.renderer.shadowMap.autoUpdate=!0,null!=u?.rendering?.resolutionScale&&(y.resolutionScale=u.rendering.resolutionScale),e.set(r,y);const I=new o(y);e.set(o,I);const x=e.get(s);e.set(s,x);const b=new g,D=new l(b),R=new d;R.setDataDir(u.dataDir);const G=Object.entries(u.shaders).map((([e,t])=>({name:e,type:t}))),H=new p(R,D,G);return e.set(p,H),(async()=>{const n=e.get(i);if(await n.start(),j.isShutdown)return;if(await b.preloadData(),j.isShutdown)return;const{scene:s,actors:o}=await t(y,u.sceneName,u.dataDir,u.shaders,u.actors,v,b,D,R);if(x.scene=s,j.isShutdown)return void y.stop();e.import([a]);for(const e of o)x.addActor(e);n.addFromScene(s),y.loop((e=>{})),j.status=5,c.value=w,w.remove(m),w.set({id:m,type:m});const r=w.get(m);c.value=null,j.gameInstance=r,w.get(f).start(),r instanceof GameInstance&&r.onStart(),j._resolver(!0)})(),j}export class GameInstance{onStart(){}onShutdown(){}}export function createHologyScene(){}export class HologyRuntime{constructor(e){this.containerInstance=e,this.status=0,this.isShutdown=!1,this.shutdownStarted=new u,this.ready=new Promise((e=>{this._resolver=e}))}getWorld(){return this.containerInstance.get(s)}getService(e){return this.containerInstance.get(e)}shutdown(){this.isShutdown=!0,this.shutdownStarted.next(),this.gameInstance instanceof GameInstance&&this.gameInstance.onShutdown(),this.containerInstance.get(m).stop();const e=this.containerInstance.get(r);e?.stop();for(const e of this.getWorld().actors)this.getWorld().removeActor(e);this.containerInstance.get(i).stop(),this.containerInstance.get(f).stop(),this.containerInstance.reset()}}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{AudioLoader as e,Group as t,LoadingManager as a,Mesh as i,Object3D as s,TextureLoader as r}from"three";import{GLTFLoader as n,MTLLoader as o,OBJLoader as c}from"three-stdlib";import{FBXLoader as h}from"three-stdlib";import{cloneMesh as l}from"../utils/mesh.js";import{pathJoin as d}from"../utils/files.js";import{Subject as p,firstValueFrom as m}from"rxjs";import{importCollisionShapes as f}from"./collision/collision-shape-import.js";import*as u from"three";import{iterateMaterials as g}from"../utils/materials.js";const w=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new a,this.glbLoader=new n(this.loadingManager),this.fbxLoader=new h(this.loadingManager),this.objLoader=new c(this.loadingManager),this.textureLoader=new r(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.makeReady=new p,this.ready=m(this.makeReady),this.collisionShapeCache=new Map}setDataDir(e){this.basePath=d(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){return d(this.basePath,e)+`?windowId=${getElectronArg("windowId")}`}async getTexture(e){return null==e?null:(await this.ready,this.cache.has(e.id)||await this.textureLoader.loadAsync(this.getUri(e.fileKey)).then((t=>(t.wrapS=L(e.texture?.wrapS),t.wrapT=L(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0,this.textureCache.set(e.id,t),t))),this.textureCache.get(e.id))}async getMesh(e){if(await this.ready,!w.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new t,animations:[]};if(!this.cache.has(e.fileKey))try{this.cache.set(e.fileKey,await this.loadMesh(e))}catch(e){return this.onError(e),{scene:new t,animations:[]}}const a=l(this.cache.get(e.fileKey).scene),s=this.cache.get(e.fileKey).animations;a.traverse((e=>{e instanceof i&&e.material instanceof Array&&(e.material=e.material.slice())}));const r=this.computeCollisionShapes(e,a),n=new AssetMeshInstance;n.add(a),n.collisionShapes=r;const o=!!e.receiveShadow??!0,c=!!e.castShadow??!1;return a.traverse((e=>{e.castShadow=c,e.receiveShadow=o})),{scene:n,animations:s}}async getAudio(e){return await this.ready,this.audioLoader.loadAsync(this.getUri(e.fileKey))}computeCollisionShapes(e,t){return this.collisionShapeCache.get(e.id)||this.collisionShapeCache.set(e.id,f(t)),this.collisionShapeCache.get(e.id)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then((e=>(e.scene=function(e,t){let a=!1;if(t.traverseVisible((e=>{b.test(e.name)&&(a=!0)})),!a)return t;const i=new u.LOD,s=[t];for(;s.length>0;){const e=s.shift(),t=e.name.match(b);if(null!=t){const a=parseInt(t[1]);0===a?i.addLevel(e,0):console.warn(`Skipping LOD level ${a} for now as LOD is not fully supported`)}else s.push(...e.children)}return i}(0,e.scene),e)))}async loadByAsset(e){const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then((e=>({scene:e.scene,animations:e.animations})));case"fbx":return this.fbxLoader.loadAsync(t).then((e=>({scene:e,animations:e.animations})));case"obj":if(null!=e.materialLib){const t=new o;t.materialOptions={normalizeRGB:!1};const a=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(a)}return this.objLoader.loadAsync(t).then((e=>(y(e),e))).then((e=>({scene:e,animations:e.animations})))}}}function y(e){if(e instanceof i)for(const t of g(e.material))t instanceof u.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(y)}export class AssetMeshInstance extends s{}export function getElectronArg(e){const t=`--${e}=`,a=window.process?.argv.find((e=>e.startsWith(t)));return a?.substring(t.length)}function L(e){switch(e){case"clamp":return u.ClampToEdgeWrapping;case"repeat":return u.RepeatWrapping;case"mirror":return u.MirroredRepeatWrapping}return u.RepeatWrapping}const b=/_LOD(\d+)$/;
1
+ import{AudioLoader as e,Group as t,LoadingManager as a,Mesh as s,Object3D as i,TextureLoader as r}from"three";import{GLTFLoader as n,MTLLoader as o,OBJLoader as h}from"three-stdlib";import{FBXLoader as c}from"three-stdlib";import{cloneMesh as l}from"../utils/mesh.js";import{pathJoin as d}from"../utils/files.js";import{Subject as p,firstValueFrom as m}from"rxjs";import{importCollisionShapes as f}from"./collision/collision-shape-import.js";import*as u from"three";import{iterateMaterials as g}from"../utils/materials.js";const w=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new a,this.glbLoader=new n(this.loadingManager),this.fbxLoader=new c(this.loadingManager),this.objLoader=new h(this.loadingManager),this.textureLoader=new r(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.makeReady=new p,this.ready=m(this.makeReady),this.collisionShapeCache=new Map}setDataDir(e){this.basePath=d(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){return d(this.basePath,e)+`?windowId=${getElectronArg("windowId")}`}async getTexture(e){return null==e?null:(await this.ready,this.cache.has(e.id)||await this.textureLoader.loadAsync(this.getUri(e.fileKey)).then((t=>(t.wrapS=L(e.texture?.wrapS),t.wrapT=L(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0,this.textureCache.set(e.id,t),t))),this.textureCache.get(e.id))}async getMesh(e){if(await this.ready,!w.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new t,animations:[]};if(!this.cache.has(e.fileKey))try{this.cache.set(e.fileKey,await this.loadMesh(e))}catch(e){return this.onError(e),{scene:new t,animations:[]}}const a=l(this.cache.get(e.fileKey).scene),i=this.cache.get(e.fileKey).animations;a.traverse((e=>{e instanceof s&&e.material instanceof Array&&(e.material=e.material.slice())}));const r=this.computeCollisionShapes(e,a),n=new AssetMeshInstance;n.add(a),n.collisionShapes=r,n.animations=i;const o=!!e.receiveShadow??!0,h=!!e.castShadow??!1;return a.traverse((e=>{e.castShadow=h,e.receiveShadow=o})),{scene:n,animations:i}}async getAudio(e){return await this.ready,this.audioLoader.loadAsync(this.getUri(e.fileKey))}computeCollisionShapes(e,t){const a=e.id+e.mesh?.collisions?.shapeType;return this.collisionShapeCache.has(a)||this.collisionShapeCache.set(a,f(t,e)),this.collisionShapeCache.get(a)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then((e=>(e.scene=function(e,t){let a=!1;if(t.traverseVisible((e=>{b.test(e.name)&&(a=!0)})),!a)return t;const s=new u.LOD,i=[t];for(;i.length>0;){const e=i.shift(),t=e.name.match(b);if(null!=t){const a=parseInt(t[1]);0===a?s.addLevel(e,0):console.warn(`Skipping LOD level ${a} for now as LOD is not fully supported`)}else i.push(...e.children)}return s}(0,e.scene),e)))}async loadByAsset(e){const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then((e=>({scene:e.scene,animations:e.animations})));case"fbx":return this.fbxLoader.loadAsync(t).then((e=>({scene:e,animations:e.animations})));case"obj":if(null!=e.materialLib){const t=new o;t.materialOptions={normalizeRGB:!1};const a=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(a)}return this.objLoader.loadAsync(t).then((e=>(y(e),e))).then((e=>({scene:e,animations:e.animations})))}}}function y(e){if(e instanceof s)for(const t of g(e.material))t instanceof u.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(y)}export class AssetMeshInstance extends i{}export function getElectronArg(e){const t=`--${e}=`,a=window.process?.argv.find((e=>e.startsWith(t)));return a?.substring(t.length)}function L(e){switch(e){case"clamp":return u.ClampToEdgeWrapping;case"repeat":return u.RepeatWrapping;case"mirror":return u.MirroredRepeatWrapping}return u.RepeatWrapping}const b=/_LOD(\d+)$/;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,5 @@
1
1
  import { Object3D } from "three";
2
2
  import { CollisionShape } from './collision-shape.js';
3
- export declare function importCollisionShapes(group: Object3D): CollisionShape[];
3
+ import { Asset } from "../../scene/model.js";
4
+ export declare function importCollisionShapes(group: Object3D, asset: Asset): CollisionShape[];
4
5
  export declare function isCollisionMesh(object: Object3D): boolean;
@@ -1,4 +1,4 @@
1
- import{Box3 as e,Euler as t,Mesh as n,Quaternion as o,Vector3 as r}from"three";import{BoxCollisionShape as i,ConvexPolyhedronCollisionShape as s,SphereCollisionShape as a,TrimeshCollisionShape as m}from"./collision-shape.js";const u=new o;export function importCollisionShapes(o){const x=[];return o.traverse((o=>{if(o instanceof n||o.isMesh){const n=function(t){if(t.name.startsWith(c.convex))return new s(t);if(t.name.startsWith(c.box)){const n=t.clone();n.quaternion.set(0,0,0,1),n.updateMatrixWorld();const o=(new e).setFromObject(n);return isFinite(o.min.lengthSq())?new i(new r(o.max.x-o.min.x,o.max.y-o.min.y,o.max.z-o.min.z)):null}if(t.name.startsWith(c.sphere)){t.geometry.computeBoundingSphere();const e=t.geometry.boundingSphere.radius*Math.max(t.scale.x,t.scale.y,t.scale.z);return new a(e)}if(t.name.startsWith(c.trimesh))return new m(t.geometry);{t.geometry.computeBoundingBox();const e=function(e){const t=e.max.x-e.min.x,n=e.max.y-e.min.y,o=e.max.z-e.min.z;return t+n+o}(h.copy(t.geometry.boundingBox).applyMatrix4(t.matrixWorld));if(e>1)return new m(t.geometry);if(e>.001)return new s(t)}}(o);null!=n&&(n.offset=o.getWorldPosition(new r),n.rotation=(new t).setFromQuaternion(o.getWorldQuaternion(u)),x.push(n),isCollisionMesh(o)&&(o.visible=!1))}})),x}export function isCollisionMesh(e){return e.name.startsWith(c.convex)||e.name.startsWith(c.box)||e.name.startsWith(c.sphere)||e.name.startsWith(c.trimesh)}var c;!function(e){e.convex="UCX_",e.box="UBX_",e.sphere="USP_",e.trimesh="UTM_"}(c||(c={}));const h=new e;
1
+ import{Box3 as e,Euler as t,Mesh as n,Quaternion as s,Vector3 as i}from"three";import{BoxCollisionShape as o,ConvexPolyhedronCollisionShape as r,SphereCollisionShape as a,TrimeshCollisionShape as m}from"./collision-shape.js";const h=new s;export function importCollisionShapes(s,c){let u=c.mesh?.collisions?.shapeType;if(null==u){let e=!1;s.traverse((t=>{(t instanceof n||t.isMesh)&&isCollisionMesh(t)&&(e=!0)})),u=e?"imported":"convex"}const p=[];return s.traverse((s=>{if(s instanceof n||s.isMesh){let n;"imported"===u?n=function(t){if(t.name.startsWith(l.convex))return new r(t);if(t.name.startsWith(l.box)){const n=t.clone();n.quaternion.set(0,0,0,1),n.updateMatrixWorld();const s=(new e).setFromObject(n);return isFinite(s.min.lengthSq())?new o(new i(s.max.x-s.min.x,s.max.y-s.min.y,s.max.z-s.min.z)):null}if(t.name.startsWith(l.sphere)){t.geometry.computeBoundingSphere();const e=t.geometry.boundingSphere.radius*Math.max(t.scale.x,t.scale.y,t.scale.z);return new a(e)}if(t.name.startsWith(l.trimesh))return new m(t.geometry)}(s):"convex"===u?n=new r(s):"mesh"===u&&(n=new m(s.geometry)),null!=n&&(n.offset=s.getWorldPosition(new i),n.rotation=(new t).setFromQuaternion(s.getWorldQuaternion(h)),p.push(n),isCollisionMesh(s)&&(s.visible=!1))}})),p}export function isCollisionMesh(e){return e.name.startsWith(l.convex)||e.name.startsWith(l.box)||e.name.startsWith(l.sphere)||e.name.startsWith(l.trimesh)}var l;!function(e){e.convex="UCX_",e.box="UBX_",e.sphere="USP_",e.trimesh="UTM_"}(l||(l={}));new e;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -35,6 +35,7 @@ export type CustomParamValue = {
35
35
  value: unknown;
36
36
  };
37
37
  export type WrapMode = 'clamp' | 'repeat' | 'mirror';
38
+ export type CollisionShapeType = 'convex' | 'mesh' | 'imported';
38
39
  export type TextureSettings = {
39
40
  flipY?: boolean;
40
41
  wrapS?: WrapMode;
@@ -65,6 +66,9 @@ export interface Asset {
65
66
  };
66
67
  mesh?: {
67
68
  rescale?: number;
69
+ collisions?: {
70
+ shapeType?: CollisionShapeType;
71
+ };
68
72
  };
69
73
  prefab?: {
70
74
  objects: SceneObject[];
@@ -21,21 +21,23 @@ export declare class ObjectStorage<T extends Entity> {
21
21
  constructor(name: string, filePathFn?: (o: ObjectIndexEntry) => string);
22
22
  setBasePath(path: string): void;
23
23
  private determineIfMetaFileShouldBeCreated;
24
+ watch(): void;
24
25
  getAll(): Promise<T[]>;
25
26
  get(id: string): Promise<T>;
26
27
  save(obj: T): Promise<T>;
27
28
  rename(obj: T, name: string): Promise<T>;
28
29
  delete(obj: T): Promise<void>;
29
30
  create(obj: Partial<T>): Promise<T>;
31
+ private serialize;
30
32
  private updateIndex;
31
33
  private get indexFilePath();
32
34
  private loadIndex;
33
35
  ensureResourceDir(): Promise<void>;
34
- saveFile(asset: T, file: File): Promise<any>;
35
- saveExtraFile(sourcePath: string, relativePath: string): Promise<any>;
36
+ saveFile(asset: T, file: File): Promise<void>;
37
+ saveExtraFile(sourcePath: string, relativePath: string): Promise<void>;
36
38
  getAssetPath(asset: T): any;
37
- replaceFile(asset: T, replacementFile: String): Promise<any>;
38
- deleteFile(fileKey: string): Promise<any>;
39
+ replaceFile(asset: T, replacementFile: string): Promise<void>;
40
+ deleteFile(fileKey: string): Promise<void>;
39
41
  private privateObjectPath;
40
42
  }
41
43
  export declare function tokenizeName(name: string): string;
@@ -1,4 +1,4 @@
1
- import{randomUUID as t}from"../../utils/uuid.js";import{pathJoin as e}from"../../utils/files.js";import{firstValueFrom as i,map as a,Subject as s,tap as n}from"rxjs";import{sleepDelay as r}from"../../utils/async.js";const h={},o={},c={};null==h.read&&window.require&&(Object.assign(h,window.require("fs")),Object.assign(o,h.promises),Object.assign(c,window.require("path")));const l=null!=h.existsSync;function d(){if(l){const t="--path=",e=window.process.argv.find((e=>e.startsWith(t)));return e?e.substring(t.length):""}return""}const u=/^[A-Z]:/;function p(...t){return 0===t.length?"":u.test(t[0])?c.join(...t):e(...t)}export class ObjectStorage{constructor(t,e){this.name=t,this.filePathFn=e,this.basePathUpdates=new s,this.basePath=this.basePathUpdates.pipe(a((t=>p(d(),t))),n((t=>{this.path=p(t,this.name),w(this.path),this.determineIfMetaFileShouldBeCreated()}))),this.loaded=i(this.basePath),this.shouldCreateIndex=!0}setBasePath(t){this.basePathUpdates.next(t)}async determineIfMetaFileShouldBeCreated(){try{(await o.readFile(p(d(),"vite.config.ts"))).toString().includes("hologyBuild")&&(this.shouldCreateIndex=!1)}catch(t){console.warn("Failed to read vite config to determine if meta files should be created")}}async getAll(){if(l){await this.loaded,await w(this.path);const t=(await o.readdir(this.path)).filter((t=>!/^[\._]/.test(t)));return(await Promise.all(t.map((t=>o.readFile(p(this.path,t)))))).map((t=>JSON.parse(t.toString())))}const t=await this.loadIndex();return Promise.all(Object.keys(t).map((t=>this.get(t))))}async get(t){const e=await this.loadIndex(),i=e[t]??Object.values(e).find((e=>e.name===t));if(null==i)return;const a=this.privateObjectPath(i);if(!l)return(await fetch(a)).json();return await f(a)?JSON.parse((await o.readFile(a)).toString()):null}async save(t){return m(),await this.loaded,await o.writeFile(this.privateObjectPath(t),JSON.stringify(t,null,2)),await this.updateIndex(),t}async rename(t,e){const i={...t,name:e},a=this.privateObjectPath(t),s=this.privateObjectPath(i);try{await o.rename(a,s)}catch(t){console.error(t),console.warn("Rename failed, retrying",{currentPath:a,newPath:s}),await r(400),await o.rename(a,s)}return await this.save(i),await this.updateIndex(),i}async delete(t){await o.unlink(this.privateObjectPath(t)),this.updateIndex()}async create(e){return m(),await this.loaded,e.id=t(),await o.writeFile(this.privateObjectPath(e),JSON.stringify(e,null,2)),await this.updateIndex(),e}async updateIndex(){m();const t=await this.getAll(),e={};for(const i of t)e[i.id]={id:i.id,name:i.name??i.id,path:i.path};if(this.cachedIndex=e,l){if(!this.shouldCreateIndex)return;await o.writeFile(this.indexFilePath,JSON.stringify(e,null,2))}}get indexFilePath(){return p(this.path,"_meta.json")}async loadIndex(){return null==this.cachedIndex&&(l?await this.updateIndex():this.cachedIndex=await(await fetch(this.indexFilePath)).json()),this.cachedIndex}async ensureResourceDir(){await w(p(this.path+"-resources"))}async saveFile(t,e){return m(),await w(p(this.path+"-resources")),o.copyFile(e.path,p(this.path+"-resources",t.fileKey))}async saveExtraFile(t,e){return m(),await w(p(this.path+"-resources")),o.copyFile(t,p(this.path+"-resources",e))}getAssetPath(t){return window&&"function"==typeof window.require?window.require("path").join(this.path+"-resources",t.fileKey):p(this.path+"-resources",t.fileKey)}async replaceFile(t,e){if(await f(e))return o.copyFile(e,p(this.path+"-resources",t.fileKey));console.error("Failed to replace file using path "+e)}async deleteFile(t){if(null==t)return;m();const e=p(this.path+"-resources",t);return await f(e)?o.unlink(e):void 0}privateObjectPath(t){return this.filePathFn?p(this.path,this.filePathFn(t)):p(this.path,tokenizeName(t.name??t.id)+".json")}}export function tokenizeName(t){return t.trim().replace(/\s/g,"_").replace(/[^a-z0-9_\-\.]/gi,"")}async function w(t){l&&(await f(t)||await o.mkdir(t,{recursive:!0}))}function f(t){return!!l&&new Promise((function(e,i){h.exists(t,(function(t){e(t)}))}))}function m(){if(!l)throw new Error("Must have direct access to filesystem")}
1
+ import{randomUUID as t}from"../../utils/uuid.js";import{pathJoin as e}from"../../utils/files.js";import{firstValueFrom as i,map as a,Observable as s,Subject as n,tap as r}from"rxjs";import{sleepDelay as h}from"../../utils/async.js";const o={},c={},l={};null==o.read&&window.require&&(Object.assign(o,window.require("fs")),Object.assign(c,o.promises),Object.assign(l,window.require("path")));const d=null!=o.existsSync;function u(){if(d){const t="--path=",e=window.process.argv.find((e=>e.startsWith(t)));return e?e.substring(t.length):""}return""}const p=/^[A-Z]:/;function w(...t){return 0===t.length?"":p.test(t[0])?l.join(...t):e(...t)}export class ObjectStorage{constructor(t,e){this.name=t,this.filePathFn=e,this.basePathUpdates=new n,this.basePath=this.basePathUpdates.pipe(a((t=>w(u(),t))),r((t=>{this.path=w(t,this.name),f(this.path),this.determineIfMetaFileShouldBeCreated()}))),this.loaded=i(this.basePath),this.shouldCreateIndex=!0}setBasePath(t){this.basePathUpdates.next(t)}async determineIfMetaFileShouldBeCreated(){try{(await c.readFile(w(u(),"vite.config.ts"))).toString().includes("hologyBuild")&&(this.shouldCreateIndex=!1)}catch(t){console.warn("Failed to read vite config to determine if meta files should be created")}}watch(){y(),function(t){return new s((e=>{const i=new AbortController,{signal:a}=i,s=c.watch(t,{recursive:!0,signal:a});return(async()=>{for await(const t of s)console.log(t),e.next(t)})(),()=>{i.abort()}}))}(this.path).pipe(a((t=>t.eventType)))}async getAll(){if(d){await this.loaded,await f(this.path);const t=(await c.readdir(this.path,{recursive:!0,withFileTypes:!0})).filter((t=>t.isFile()&&t.name.endsWith(".json")&&!/^[\._]/.test(t.name)));return await Promise.all(t.map((t=>c.readFile(w(this.path,t.path,t.name)).then((e=>({...JSON.parse(e.toString()),path:t}))))))}const t=await this.loadIndex();return Promise.all(Object.keys(t).map((t=>this.get(t))))}async get(t){const e=await this.loadIndex(),i=e[t]??Object.values(e).find((e=>e.name===t));if(null==i)return;const a=this.privateObjectPath(i);if(!d)return(await fetch(a)).json();return await m(a)?JSON.parse((await c.readFile(a)).toString()):null}async save(t){return y(),await this.loaded,await c.writeFile(this.privateObjectPath(t),this.serialize(t)),await this.updateIndex(),t}async rename(t,e){const i={...t,name:e},a=this.privateObjectPath(t),s=this.privateObjectPath(i);try{await c.rename(a,s)}catch(t){console.error(t),console.warn("Rename failed, retrying",{currentPath:a,newPath:s}),await h(400),await c.rename(a,s)}return await this.save(i),await this.updateIndex(),i}async delete(t){await c.unlink(this.privateObjectPath(t)),this.updateIndex()}async create(e){return y(),await this.loaded,e.id=t(),await c.writeFile(this.privateObjectPath(e),this.serialize(e)),await this.updateIndex(),e}serialize(t){const e={...t};return delete e.path,JSON.stringify(e,null,2)}async updateIndex(){y();const t=await this.getAll(),e={};for(const i of t)e[i.id]={id:i.id,name:i.name??i.id,path:i.path};if(this.cachedIndex=e,d){if(!this.shouldCreateIndex)return;await c.writeFile(this.indexFilePath,JSON.stringify(e,null,2))}}get indexFilePath(){return w(this.path,"_meta.json")}async loadIndex(){return null==this.cachedIndex&&(d?await this.updateIndex():this.cachedIndex=await(await fetch(this.indexFilePath)).json()),this.cachedIndex}async ensureResourceDir(){await f(w(this.path+"-resources"))}async saveFile(t,e){return y(),await f(w(this.path+"-resources")),c.copyFile(e.path,w(this.path+"-resources",t.fileKey))}async saveExtraFile(t,e){return y(),await f(w(this.path+"-resources")),c.copyFile(t,w(this.path+"-resources",e))}getAssetPath(t){return window&&"function"==typeof window.require?window.require("path").join(this.path+"-resources",t.fileKey):w(this.path+"-resources",t.fileKey)}async replaceFile(t,e){if(await m(e))return c.copyFile(e,w(this.path+"-resources",t.fileKey));console.error("Failed to replace file using path "+e)}async deleteFile(t){if(null==t)return;y();const e=w(this.path+"-resources",t);return await m(e)?c.unlink(e):void 0}privateObjectPath(t){return this.filePathFn?w(this.path,this.filePathFn(t)):w(this.path,tokenizeName(t.name??t.id)+".json")}}export function tokenizeName(t){return t.trim().replace(/\s/g,"_").replace(/[^a-z0-9_\-\.]/gi,"")}async function f(t){d&&(await m(t)||await c.mkdir(t,{recursive:!0}))}function m(t){return!!d&&new Promise((function(e,i){o.exists(t,(function(t){e(t)}))}))}function y(){if(!d)throw new Error("Must have direct access to filesystem")}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hology/core",
3
- "version": "0.0.49",
3
+ "version": "0.0.51",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",