@underpostnet/cyberia 3.2.80

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.
Files changed (821) hide show
  1. package/.dockerignore +14 -0
  2. package/.env.example +144 -0
  3. package/.github/workflows/cyberia-client.cd.yml +40 -0
  4. package/.github/workflows/cyberia-server.cd.yml +40 -0
  5. package/.github/workflows/docker-image.cyberia-client.ci.yml +71 -0
  6. package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +70 -0
  7. package/.github/workflows/docker-image.cyberia-server.ci.yml +71 -0
  8. package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +71 -0
  9. package/.github/workflows/docker-image.engine-cyberia.ci.yml +53 -0
  10. package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +53 -0
  11. package/.github/workflows/engine-cyberia.cd.yml +157 -0
  12. package/.github/workflows/engine-cyberia.ci.yml +125 -0
  13. package/.github/workflows/ghpkg.ci.yml +160 -0
  14. package/.github/workflows/gitlab.ci.yml +20 -0
  15. package/.github/workflows/hardhat.ci.yml +82 -0
  16. package/.github/workflows/npmpkg.ci.yml +126 -0
  17. package/.github/workflows/publish.ci.yml +87 -0
  18. package/.github/workflows/publish.cyberia.ci.yml +79 -0
  19. package/.github/workflows/pwa-microservices-template-page.cd.yml +65 -0
  20. package/.github/workflows/pwa-microservices-template-test.ci.yml +33 -0
  21. package/.github/workflows/release.cd.yml +46 -0
  22. package/.nycrc +9 -0
  23. package/.prettierignore +12 -0
  24. package/.prettierrc +9 -0
  25. package/.vscode/extensions.json +10 -0
  26. package/.vscode/settings.json +26 -0
  27. package/CHANGELOG.md +2516 -0
  28. package/CLI-HELP.md +1099 -0
  29. package/Dockerfile +161 -0
  30. package/Dockerfile.dev +161 -0
  31. package/Dockerfile.test +165 -0
  32. package/LICENSE +21 -0
  33. package/README.md +259 -0
  34. package/baremetal/commission-workflows.json +211 -0
  35. package/baremetal/packer-workflows.json +24 -0
  36. package/bin/build.js +261 -0
  37. package/bin/build.template.js +33 -0
  38. package/bin/cyberia.js +5627 -0
  39. package/bin/deploy.js +1547 -0
  40. package/bin/index.js +5627 -0
  41. package/bump.config.js +27 -0
  42. package/compose.env +144 -0
  43. package/conf.js +952 -0
  44. package/deployment.yaml +418 -0
  45. package/docker-compose.yml +434 -0
  46. package/examples/static-page/README.md +150 -0
  47. package/examples/static-page/ssr-components/CustomPage.js +554 -0
  48. package/examples/static-page/static-config-example.json +57 -0
  49. package/hardhat/.env.example +31 -0
  50. package/hardhat/contracts/ObjectLayerToken.sol +391 -0
  51. package/hardhat/deployments/.gitkeep +0 -0
  52. package/hardhat/deployments/hardhat-ObjectLayerToken.json +11 -0
  53. package/hardhat/hardhat.config.js +136 -0
  54. package/hardhat/ignition/modules/.gitkeep +0 -0
  55. package/hardhat/ignition/modules/ObjectLayerToken.js +21 -0
  56. package/hardhat/networks/besu-object-layer.network.json +138 -0
  57. package/hardhat/package-lock.json +2871 -0
  58. package/hardhat/package.json +43 -0
  59. package/hardhat/scripts/deployObjectLayerToken.js +98 -0
  60. package/hardhat/test/ObjectLayerToken.js +696 -0
  61. package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
  62. package/hardhat/types/ethers-contracts/common.ts +92 -0
  63. package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
  64. package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
  65. package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
  66. package/hardhat/types/ethers-contracts/index.ts +6 -0
  67. package/ipfs/configure-ipfs.sh +13 -0
  68. package/jsconfig.json +9 -0
  69. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +48 -0
  70. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +48 -0
  71. package/manifests/deployment/adminer/deployment.yaml +32 -0
  72. package/manifests/deployment/adminer/kustomization.yaml +7 -0
  73. package/manifests/deployment/adminer/service.yaml +13 -0
  74. package/manifests/deployment/dd-cyberia-development/deployment.yaml +418 -0
  75. package/manifests/deployment/dd-cyberia-development/grpc-service.yaml +17 -0
  76. package/manifests/deployment/dd-cyberia-development/proxy.yaml +189 -0
  77. package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +164 -0
  78. package/manifests/deployment/dd-default-development/deployment.yaml +163 -0
  79. package/manifests/deployment/dd-default-development/proxy.yaml +46 -0
  80. package/manifests/deployment/fastapi/backend-deployment.yml +120 -0
  81. package/manifests/deployment/fastapi/backend-service.yml +19 -0
  82. package/manifests/deployment/fastapi/frontend-deployment.yml +54 -0
  83. package/manifests/deployment/fastapi/frontend-service.yml +15 -0
  84. package/manifests/deployment/fastapi/initial_data.sh +8 -0
  85. package/manifests/deployment/kafka/deployment.yaml +67 -0
  86. package/manifests/deployment/mongo-express/deployment.yaml +62 -0
  87. package/manifests/deployment/phpmyadmin/deployment.yaml +54 -0
  88. package/manifests/deployment/playwright/deployment.yaml +52 -0
  89. package/manifests/deployment/spark/spark-pi-py.yaml +20 -0
  90. package/manifests/deployment/tensorflow/tf-gpu-test.yaml +63 -0
  91. package/manifests/envoy-service-nodeport.yaml +22 -0
  92. package/manifests/grafana/deployment.yaml +64 -0
  93. package/manifests/grafana/kustomization.yaml +7 -0
  94. package/manifests/grafana/pvc.yaml +12 -0
  95. package/manifests/grafana/service.yaml +14 -0
  96. package/manifests/grafana/storage-class.yaml +9 -0
  97. package/manifests/ipfs/configmap.yaml +64 -0
  98. package/manifests/ipfs/headless-service.yaml +35 -0
  99. package/manifests/ipfs/kustomization.yaml +8 -0
  100. package/manifests/ipfs/statefulset.yaml +149 -0
  101. package/manifests/ipfs/storage-class.yaml +9 -0
  102. package/manifests/kind-config-dev.yaml +20 -0
  103. package/manifests/kind-config.yaml +12 -0
  104. package/manifests/kubeadm-calico-config.yaml +14 -0
  105. package/manifests/letsencrypt-prod.yaml +14 -0
  106. package/manifests/lxd/lxd-admin-profile.yaml +26 -0
  107. package/manifests/lxd/lxd-preseed.yaml +30 -0
  108. package/manifests/mariadb/kustomization.yaml +9 -0
  109. package/manifests/mariadb/pv.yaml +12 -0
  110. package/manifests/mariadb/pvc.yaml +10 -0
  111. package/manifests/mariadb/service.yaml +10 -0
  112. package/manifests/mariadb/statefulset.yaml +56 -0
  113. package/manifests/mariadb/storage-class.yaml +10 -0
  114. package/manifests/mongodb/headless-service.yaml +10 -0
  115. package/manifests/mongodb/kustomization.yaml +11 -0
  116. package/manifests/mongodb/pv-pvc.yaml +59 -0
  117. package/manifests/mongodb/statefulset.yaml +113 -0
  118. package/manifests/mongodb/storage-class.yaml +9 -0
  119. package/manifests/mongodb-4.4/headless-service.yaml +10 -0
  120. package/manifests/mongodb-4.4/kustomization.yaml +9 -0
  121. package/manifests/mongodb-4.4/mongodb-nodeport.yaml +17 -0
  122. package/manifests/mongodb-4.4/pv-pvc.yaml +19 -0
  123. package/manifests/mongodb-4.4/service-deployment.yaml +61 -0
  124. package/manifests/mongodb-4.4/statefulset.yaml +79 -0
  125. package/manifests/mongodb-4.4/storage-class.yaml +9 -0
  126. package/manifests/mysql/kustomization.yaml +7 -0
  127. package/manifests/mysql/pv-pvc.yaml +27 -0
  128. package/manifests/mysql/statefulset.yaml +55 -0
  129. package/manifests/postgresql/configmap.yaml +9 -0
  130. package/manifests/postgresql/kustomization.yaml +10 -0
  131. package/manifests/postgresql/pv.yaml +15 -0
  132. package/manifests/postgresql/pvc.yaml +13 -0
  133. package/manifests/postgresql/service.yaml +10 -0
  134. package/manifests/postgresql/statefulset.yaml +37 -0
  135. package/manifests/prometheus/deployment.yaml +82 -0
  136. package/manifests/pv-pvc-dd.yaml +34 -0
  137. package/manifests/valkey/kustomization.yaml +7 -0
  138. package/manifests/valkey/service.yaml +10 -0
  139. package/manifests/valkey/statefulset.yaml +37 -0
  140. package/manifests/valkey/valkey-nodeport.yaml +17 -0
  141. package/mongodb/entrypoint.sh +76 -0
  142. package/nginx.conf +128 -0
  143. package/nodemon.json +6 -0
  144. package/package.json +101 -0
  145. package/packer/images/Rocky9Amd64/Makefile +62 -0
  146. package/packer/images/Rocky9Amd64/QUICKSTART.md +113 -0
  147. package/packer/images/Rocky9Amd64/README.md +122 -0
  148. package/packer/images/Rocky9Amd64/http/rocky9.ks.pkrtpl.hcl +114 -0
  149. package/packer/images/Rocky9Amd64/rocky9.pkr.hcl +164 -0
  150. package/packer/images/Rocky9Arm64/Makefile +69 -0
  151. package/packer/images/Rocky9Arm64/README.md +122 -0
  152. package/packer/images/Rocky9Arm64/http/rocky9.ks.pkrtpl.hcl +114 -0
  153. package/packer/images/Rocky9Arm64/rocky9.pkr.hcl +171 -0
  154. package/packer/scripts/fuse-nbd +64 -0
  155. package/packer/scripts/fuse-tar-root +63 -0
  156. package/proxy.yaml +189 -0
  157. package/pv-pvc.yaml +164 -0
  158. package/scripts/device-scan.sh +65 -0
  159. package/scripts/disk-clean.sh +182 -0
  160. package/scripts/disk-devices.sh +13 -0
  161. package/scripts/gen-fqdns.sh +14 -0
  162. package/scripts/gpu-diag.sh +19 -0
  163. package/scripts/ip-info.sh +118 -0
  164. package/scripts/ipxe-setup.sh +200 -0
  165. package/scripts/k3s-node-setup.sh +124 -0
  166. package/scripts/kubeadm-node-setup.sh +317 -0
  167. package/scripts/link-local-underpost-cli.sh +6 -0
  168. package/scripts/lxd-vm-setup.sh +208 -0
  169. package/scripts/maas-nat-firewalld.sh +145 -0
  170. package/scripts/maas-setup.sh +135 -0
  171. package/scripts/maas-upload-boot-resource.sh +183 -0
  172. package/scripts/nat-iptables.sh +111 -0
  173. package/scripts/nvim.sh +91 -0
  174. package/scripts/packer-init-vars-file.sh +40 -0
  175. package/scripts/packer-setup.sh +289 -0
  176. package/scripts/ports-ls.sh +33 -0
  177. package/scripts/quick-tftp.sh +19 -0
  178. package/scripts/rhel-grpc-setup.sh +56 -0
  179. package/scripts/rocky-kickstart.sh +986 -0
  180. package/scripts/rocky-pwa.sh +200 -0
  181. package/scripts/rocky-setup.sh +106 -0
  182. package/scripts/rpmfusion-ffmpeg-setup.sh +32 -0
  183. package/scripts/ssl.sh +170 -0
  184. package/scripts/test-monitor.sh +248 -0
  185. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +30 -0
  186. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +155 -0
  187. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +39 -0
  188. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +382 -0
  189. package/src/api/core/core.controller.js +8 -0
  190. package/src/api/core/core.model.js +11 -0
  191. package/src/api/core/core.router.js +23 -0
  192. package/src/api/core/core.service.js +30 -0
  193. package/src/api/crypto/crypto.controller.js +10 -0
  194. package/src/api/crypto/crypto.model.js +23 -0
  195. package/src/api/crypto/crypto.router.js +23 -0
  196. package/src/api/crypto/crypto.service.js +64 -0
  197. package/src/api/cyberia-action/cyberia-action.controller.js +8 -0
  198. package/src/api/cyberia-action/cyberia-action.model.js +79 -0
  199. package/src/api/cyberia-action/cyberia-action.router.js +21 -0
  200. package/src/api/cyberia-action/cyberia-action.service.js +58 -0
  201. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +27 -0
  202. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +100 -0
  203. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +70 -0
  204. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +152 -0
  205. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +8 -0
  206. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
  207. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +20 -0
  208. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +57 -0
  209. package/src/api/cyberia-entity/cyberia-entity.controller.js +6 -0
  210. package/src/api/cyberia-entity/cyberia-entity.model.js +25 -0
  211. package/src/api/cyberia-entity/cyberia-entity.router.js +17 -0
  212. package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
  213. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +6 -0
  214. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +67 -0
  215. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +17 -0
  216. package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +46 -0
  217. package/src/api/cyberia-instance/cyberia-fallback-world.js +337 -0
  218. package/src/api/cyberia-instance/cyberia-instance-boot.service.js +57 -0
  219. package/src/api/cyberia-instance/cyberia-instance-map.service.js +583 -0
  220. package/src/api/cyberia-instance/cyberia-instance.controller.js +42 -0
  221. package/src/api/cyberia-instance/cyberia-instance.model.js +117 -0
  222. package/src/api/cyberia-instance/cyberia-instance.router.js +75 -0
  223. package/src/api/cyberia-instance/cyberia-instance.service.js +190 -0
  224. package/src/api/cyberia-instance/cyberia-portal-connector.js +260 -0
  225. package/src/api/cyberia-instance/cyberia-world-generator.js +618 -0
  226. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +6 -0
  227. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +200 -0
  228. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +17 -0
  229. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +46 -0
  230. package/src/api/cyberia-map/cyberia-map.controller.js +6 -0
  231. package/src/api/cyberia-map/cyberia-map.model.js +33 -0
  232. package/src/api/cyberia-map/cyberia-map.router.js +19 -0
  233. package/src/api/cyberia-map/cyberia-map.service.js +76 -0
  234. package/src/api/cyberia-quest/cyberia-quest.controller.js +9 -0
  235. package/src/api/cyberia-quest/cyberia-quest.model.js +67 -0
  236. package/src/api/cyberia-quest/cyberia-quest.router.js +26 -0
  237. package/src/api/cyberia-quest/cyberia-quest.service.js +97 -0
  238. package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +6 -0
  239. package/src/api/cyberia-quest-progress/cyberia-quest-progress.model.js +49 -0
  240. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +21 -0
  241. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +42 -0
  242. package/src/api/cyberia-saga/cyberia-saga.controller.js +6 -0
  243. package/src/api/cyberia-saga/cyberia-saga.model.js +59 -0
  244. package/src/api/cyberia-saga/cyberia-saga.router.js +17 -0
  245. package/src/api/cyberia-saga/cyberia-saga.service.js +42 -0
  246. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +1076 -0
  247. package/src/api/cyberia-skill/cyberia-skill.controller.js +6 -0
  248. package/src/api/cyberia-skill/cyberia-skill.model.js +50 -0
  249. package/src/api/cyberia-skill/cyberia-skill.router.js +17 -0
  250. package/src/api/cyberia-skill/cyberia-skill.service.js +42 -0
  251. package/src/api/default/default.controller.js +6 -0
  252. package/src/api/default/default.model.js +20 -0
  253. package/src/api/default/default.router.js +21 -0
  254. package/src/api/default/default.service.js +42 -0
  255. package/src/api/document/document.controller.js +9 -0
  256. package/src/api/document/document.model.js +95 -0
  257. package/src/api/document/document.router.js +32 -0
  258. package/src/api/document/document.service.js +633 -0
  259. package/src/api/file/file.controller.js +15 -0
  260. package/src/api/file/file.model.js +127 -0
  261. package/src/api/file/file.ref.json +39 -0
  262. package/src/api/file/file.router.js +36 -0
  263. package/src/api/file/file.service.js +499 -0
  264. package/src/api/instance/instance.controller.js +8 -0
  265. package/src/api/instance/instance.model.js +34 -0
  266. package/src/api/instance/instance.router.js +27 -0
  267. package/src/api/instance/instance.service.js +75 -0
  268. package/src/api/ipfs/ipfs.controller.js +8 -0
  269. package/src/api/ipfs/ipfs.model.js +77 -0
  270. package/src/api/ipfs/ipfs.router.js +26 -0
  271. package/src/api/ipfs/ipfs.service.js +145 -0
  272. package/src/api/object-layer/object-layer.controller.js +18 -0
  273. package/src/api/object-layer/object-layer.model.js +200 -0
  274. package/src/api/object-layer/object-layer.router.js +729 -0
  275. package/src/api/object-layer/object-layer.service.js +894 -0
  276. package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +6 -0
  277. package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +93 -0
  278. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +17 -0
  279. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +46 -0
  280. package/src/api/test/test.controller.js +14 -0
  281. package/src/api/test/test.model.js +14 -0
  282. package/src/api/test/test.router.js +23 -0
  283. package/src/api/test/test.service.js +35 -0
  284. package/src/api/types.js +24 -0
  285. package/src/api/user/guest.service.js +100 -0
  286. package/src/api/user/postman_collection.json +216 -0
  287. package/src/api/user/user.build.js +16 -0
  288. package/src/api/user/user.controller.js +35 -0
  289. package/src/api/user/user.model.js +142 -0
  290. package/src/api/user/user.router.js +367 -0
  291. package/src/api/user/user.service.js +582 -0
  292. package/src/api.js +23 -0
  293. package/src/cli/baremetal.js +3947 -0
  294. package/src/cli/cloud-init.js +673 -0
  295. package/src/cli/cluster.js +1395 -0
  296. package/src/cli/db.js +1533 -0
  297. package/src/cli/deploy.js +1542 -0
  298. package/src/cli/docker-compose.js +802 -0
  299. package/src/cli/env.js +177 -0
  300. package/src/cli/fs.js +380 -0
  301. package/src/cli/image.js +389 -0
  302. package/src/cli/index.js +1059 -0
  303. package/src/cli/ipfs.js +182 -0
  304. package/src/cli/kickstart.js +271 -0
  305. package/src/cli/kubectl.js +214 -0
  306. package/src/cli/lxd.js +1232 -0
  307. package/src/cli/monitor.js +659 -0
  308. package/src/cli/release.js +595 -0
  309. package/src/cli/repository.js +1969 -0
  310. package/src/cli/run.js +3326 -0
  311. package/src/cli/secrets.js +151 -0
  312. package/src/cli/ssh.js +975 -0
  313. package/src/cli/static.js +653 -0
  314. package/src/cli/system.js +332 -0
  315. package/src/cli/test.js +176 -0
  316. package/src/client/Cryptokoyn.index.js +30 -0
  317. package/src/client/CyberiaPortal.index.js +31 -0
  318. package/src/client/Default.index.js +77 -0
  319. package/src/client/Itemledger.index.js +35 -0
  320. package/src/client/Underpost.index.js +31 -0
  321. package/src/client/components/core/404.js +20 -0
  322. package/src/client/components/core/500.js +20 -0
  323. package/src/client/components/core/Account.js +630 -0
  324. package/src/client/components/core/AgGrid.js +238 -0
  325. package/src/client/components/core/Alert.js +76 -0
  326. package/src/client/components/core/AppStore.js +69 -0
  327. package/src/client/components/core/Auth.js +353 -0
  328. package/src/client/components/core/Badge.js +26 -0
  329. package/src/client/components/core/Blockchain.js +41 -0
  330. package/src/client/components/core/Blog.js +9 -0
  331. package/src/client/components/core/BtnIcon.js +109 -0
  332. package/src/client/components/core/CalendarCore.js +437 -0
  333. package/src/client/components/core/Chat.js +62 -0
  334. package/src/client/components/core/ClientEvents.js +163 -0
  335. package/src/client/components/core/ColorPaletteElement.js +309 -0
  336. package/src/client/components/core/CommonJs.js +1014 -0
  337. package/src/client/components/core/Content.js +349 -0
  338. package/src/client/components/core/Css.js +1134 -0
  339. package/src/client/components/core/CssCore.js +881 -0
  340. package/src/client/components/core/D3Chart.js +44 -0
  341. package/src/client/components/core/Docs.js +478 -0
  342. package/src/client/components/core/DropDown.js +321 -0
  343. package/src/client/components/core/EventBus.js +96 -0
  344. package/src/client/components/core/EventsUI.js +130 -0
  345. package/src/client/components/core/FileExplorer.js +1406 -0
  346. package/src/client/components/core/FullScreen.js +201 -0
  347. package/src/client/components/core/Input.js +537 -0
  348. package/src/client/components/core/Keyboard.js +80 -0
  349. package/src/client/components/core/KeyboardAvoidance.js +145 -0
  350. package/src/client/components/core/LoadingAnimation.js +152 -0
  351. package/src/client/components/core/LogIn.js +212 -0
  352. package/src/client/components/core/LogOut.js +72 -0
  353. package/src/client/components/core/Logger.js +22 -0
  354. package/src/client/components/core/Modal.js +2956 -0
  355. package/src/client/components/core/NotificationManager.js +80 -0
  356. package/src/client/components/core/Pagination.js +252 -0
  357. package/src/client/components/core/Panel.js +1308 -0
  358. package/src/client/components/core/PanelForm.js +915 -0
  359. package/src/client/components/core/Polyhedron.js +947 -0
  360. package/src/client/components/core/PublicProfile.js +895 -0
  361. package/src/client/components/core/Recover.js +211 -0
  362. package/src/client/components/core/Responsive.js +146 -0
  363. package/src/client/components/core/RichText.js +33 -0
  364. package/src/client/components/core/Router.js +523 -0
  365. package/src/client/components/core/Scroll.js +76 -0
  366. package/src/client/components/core/SearchBox.js +1007 -0
  367. package/src/client/components/core/SignUp.js +153 -0
  368. package/src/client/components/core/SocketIo.js +163 -0
  369. package/src/client/components/core/SocketIoHandler.js +75 -0
  370. package/src/client/components/core/Stream.js +161 -0
  371. package/src/client/components/core/ToggleSwitch.js +89 -0
  372. package/src/client/components/core/ToolTip.js +78 -0
  373. package/src/client/components/core/Translate.js +694 -0
  374. package/src/client/components/core/Validator.js +140 -0
  375. package/src/client/components/core/VanillaJs.js +485 -0
  376. package/src/client/components/core/Wallet.js +95 -0
  377. package/src/client/components/core/WebComponent.js +44 -0
  378. package/src/client/components/core/Webhook.js +58 -0
  379. package/src/client/components/core/Worker.js +313 -0
  380. package/src/client/components/core/windowGetDimensions.js +269 -0
  381. package/src/client/components/cryptokoyn/AppShellCryptokoyn.js +352 -0
  382. package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
  383. package/src/client/components/cryptokoyn/CssCryptokoyn.js +212 -0
  384. package/src/client/components/cryptokoyn/LogInCryptokoyn.js +16 -0
  385. package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +12 -0
  386. package/src/client/components/cryptokoyn/RouterCryptokoyn.js +37 -0
  387. package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +16 -0
  388. package/src/client/components/cryptokoyn/SignUpCryptokoyn.js +11 -0
  389. package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +6 -0
  390. package/src/client/components/cyberia/ActionEngineCyberia.js +1867 -0
  391. package/src/client/components/cyberia/EntityEngineCyberia.js +585 -0
  392. package/src/client/components/cyberia/InstanceEngineCyberia.js +1088 -0
  393. package/src/client/components/cyberia/InstanceSelectionView.js +900 -0
  394. package/src/client/components/cyberia/MapEngineCyberia.js +1976 -0
  395. package/src/client/components/cyberia/ObjectLayerEngine.js +1540 -0
  396. package/src/client/components/cyberia/ObjectLayerEngineModal.js +2420 -0
  397. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +1522 -0
  398. package/src/client/components/cyberia/SharedDefaultsCyberia.js +528 -0
  399. package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +772 -0
  400. package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
  401. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +254 -0
  402. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +21 -0
  403. package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +16 -0
  404. package/src/client/components/cyberia-portal/MainBodyCyberiaPortal.js +518 -0
  405. package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +72 -0
  406. package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +16 -0
  407. package/src/client/components/cyberia-portal/SignUpCyberiaPortal.js +13 -0
  408. package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +6 -0
  409. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +48 -0
  410. package/src/client/components/default/AppShellDefault.js +765 -0
  411. package/src/client/components/default/AppStoreDefault.js +5 -0
  412. package/src/client/components/default/CommonDefault.js +29 -0
  413. package/src/client/components/default/CssDefault.js +27 -0
  414. package/src/client/components/default/LogInDefault.js +16 -0
  415. package/src/client/components/default/LogOutDefault.js +12 -0
  416. package/src/client/components/default/RouterDefault.js +47 -0
  417. package/src/client/components/default/SettingsDefault.js +16 -0
  418. package/src/client/components/default/SignUpDefault.js +11 -0
  419. package/src/client/components/default/SocketIoDefault.js +6 -0
  420. package/src/client/components/default/TranslateDefault.js +7 -0
  421. package/src/client/components/itemledger/AppShellItemledger.js +353 -0
  422. package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
  423. package/src/client/components/itemledger/CssItemledger.js +212 -0
  424. package/src/client/components/itemledger/LogInItemledger.js +17 -0
  425. package/src/client/components/itemledger/LogOutItemledger.js +12 -0
  426. package/src/client/components/itemledger/RouterItemledger.js +38 -0
  427. package/src/client/components/itemledger/SettingsItemledger.js +16 -0
  428. package/src/client/components/itemledger/SignUpItemledger.js +11 -0
  429. package/src/client/components/itemledger/SocketIoItemledger.js +6 -0
  430. package/src/client/components/itemledger/TranslateItemledger.js +7 -0
  431. package/src/client/components/underpost/AppShellUnderpost.js +691 -0
  432. package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
  433. package/src/client/components/underpost/CssUnderpost.js +281 -0
  434. package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +879 -0
  435. package/src/client/components/underpost/DocumentSearchProvider.js +448 -0
  436. package/src/client/components/underpost/LabGalleryUnderpost.js +79 -0
  437. package/src/client/components/underpost/LogInUnderpost.js +25 -0
  438. package/src/client/components/underpost/LogOutUnderpost.js +17 -0
  439. package/src/client/components/underpost/RouterUnderpost.js +45 -0
  440. package/src/client/components/underpost/SettingsUnderpost.js +16 -0
  441. package/src/client/components/underpost/SignUpUnderpost.js +11 -0
  442. package/src/client/components/underpost/SocketIoUnderpost.js +6 -0
  443. package/src/client/components/underpost/TranslateUnderpost.js +10 -0
  444. package/src/client/public/cryptokoyn/assets/banner/koyn-social.png +0 -0
  445. package/src/client/public/cryptokoyn/assets/logo/base-icon.png +0 -0
  446. package/src/client/public/cryptokoyn/assets/logo/cryptokoyn.png +0 -0
  447. package/src/client/public/cryptokoyn/assets/splash/android-chrome-144x144.png +0 -0
  448. package/src/client/public/cryptokoyn/assets/splash/android-chrome-192x192.png +0 -0
  449. package/src/client/public/cryptokoyn/assets/splash/android-chrome-256x256.png +0 -0
  450. package/src/client/public/cryptokoyn/assets/splash/android-chrome-36x36.png +0 -0
  451. package/src/client/public/cryptokoyn/assets/splash/android-chrome-48x48.png +0 -0
  452. package/src/client/public/cryptokoyn/assets/splash/android-chrome-72x72.png +0 -0
  453. package/src/client/public/cryptokoyn/assets/splash/android-chrome-96x96.png +0 -0
  454. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-114x114-precomposed.png +0 -0
  455. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-114x114.png +0 -0
  456. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-120x120-precomposed.png +0 -0
  457. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-120x120.png +0 -0
  458. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-144x144-precomposed.png +0 -0
  459. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-144x144.png +0 -0
  460. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-152x152-precomposed.png +0 -0
  461. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-152x152.png +0 -0
  462. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-180x180-precomposed.png +0 -0
  463. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-180x180.png +0 -0
  464. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-57x57-precomposed.png +0 -0
  465. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-57x57.png +0 -0
  466. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-60x60-precomposed.png +0 -0
  467. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-60x60.png +0 -0
  468. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-72x72-precomposed.png +0 -0
  469. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-72x72.png +0 -0
  470. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-76x76-precomposed.png +0 -0
  471. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-76x76.png +0 -0
  472. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon-precomposed.png +0 -0
  473. package/src/client/public/cryptokoyn/assets/splash/apple-touch-icon.png +0 -0
  474. package/src/client/public/cryptokoyn/assets/splash/favicon-16x16.png +0 -0
  475. package/src/client/public/cryptokoyn/assets/splash/favicon-32x32.png +0 -0
  476. package/src/client/public/cryptokoyn/assets/splash/mstile-144x144.png +0 -0
  477. package/src/client/public/cryptokoyn/assets/splash/mstile-150x150.png +0 -0
  478. package/src/client/public/cryptokoyn/assets/splash/mstile-310x150.png +0 -0
  479. package/src/client/public/cryptokoyn/assets/splash/mstile-310x310.png +0 -0
  480. package/src/client/public/cryptokoyn/assets/splash/mstile-70x70.png +0 -0
  481. package/src/client/public/cryptokoyn/assets/splash/safari-pinned-tab.svg +42 -0
  482. package/src/client/public/cryptokoyn/browserconfig.xml +12 -0
  483. package/src/client/public/cryptokoyn/favicon.ico +0 -0
  484. package/src/client/public/cryptokoyn/microdata.json +85 -0
  485. package/src/client/public/cryptokoyn/site.webmanifest +57 -0
  486. package/src/client/public/cryptokoyn/sitemap +148 -0
  487. package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +307 -0
  488. package/src/client/public/cyberia-docs/ARCHITECTURE.md +309 -0
  489. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +204 -0
  490. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +341 -0
  491. package/src/client/public/cyberia-docs/CYBERIA-LORE.md +84 -0
  492. package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +394 -0
  493. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +294 -0
  494. package/src/client/public/cyberia-docs/CYBERIA.md +259 -0
  495. package/src/client/public/cyberia-docs/ENTITY-PROFILE.md +242 -0
  496. package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +300 -0
  497. package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +309 -0
  498. package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +228 -0
  499. package/src/client/public/cyberia-docs/ROADMAP.md +240 -0
  500. package/src/client/public/cyberia-docs/UNDERPOST-PLATFORM.md +106 -0
  501. package/src/client/public/cyberia-docs/WHITE-PAPER.md +740 -0
  502. package/src/client/public/default/android-chrome-144x144.png +0 -0
  503. package/src/client/public/default/android-chrome-192x192.png +0 -0
  504. package/src/client/public/default/android-chrome-256x256.png +0 -0
  505. package/src/client/public/default/android-chrome-36x36.png +0 -0
  506. package/src/client/public/default/android-chrome-384x384.png +0 -0
  507. package/src/client/public/default/android-chrome-48x48.png +0 -0
  508. package/src/client/public/default/android-chrome-512x512.png +0 -0
  509. package/src/client/public/default/android-chrome-72x72.png +0 -0
  510. package/src/client/public/default/android-chrome-96x96.png +0 -0
  511. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  512. package/src/client/public/default/apple-touch-icon-114x114-precomposed.png +0 -0
  513. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  514. package/src/client/public/default/apple-touch-icon-120x120-precomposed.png +0 -0
  515. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  516. package/src/client/public/default/apple-touch-icon-144x144-precomposed.png +0 -0
  517. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  518. package/src/client/public/default/apple-touch-icon-152x152-precomposed.png +0 -0
  519. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  520. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  521. package/src/client/public/default/apple-touch-icon-180x180-precomposed.png +0 -0
  522. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  523. package/src/client/public/default/apple-touch-icon-57x57-precomposed.png +0 -0
  524. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  525. package/src/client/public/default/apple-touch-icon-60x60-precomposed.png +0 -0
  526. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  527. package/src/client/public/default/apple-touch-icon-72x72-precomposed.png +0 -0
  528. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  529. package/src/client/public/default/apple-touch-icon-76x76-precomposed.png +0 -0
  530. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  531. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  532. package/src/client/public/default/apple-touch-icon.png +0 -0
  533. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  534. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  535. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  536. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  537. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  538. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  539. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  540. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  541. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  542. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  543. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  544. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  545. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  546. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  547. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  548. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  549. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  550. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  551. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  552. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  553. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  554. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  555. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  556. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  557. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  558. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  559. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  560. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  561. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  562. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  563. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  564. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  565. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  566. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  567. package/src/client/public/default/assets/background/dark.jpg +0 -0
  568. package/src/client/public/default/assets/background/dark.svg +557 -0
  569. package/src/client/public/default/assets/background/white.jpg +0 -0
  570. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  571. package/src/client/public/default/assets/background/white0.jpg +0 -0
  572. package/src/client/public/default/assets/logo/base-icon.png +0 -0
  573. package/src/client/public/default/assets/logo/underpost.gif +0 -0
  574. package/src/client/public/default/assets/mailer/api-user-check.png +0 -0
  575. package/src/client/public/default/assets/mailer/api-user-default-avatar.png +0 -0
  576. package/src/client/public/default/assets/mailer/api-user-invalid-token.png +0 -0
  577. package/src/client/public/default/assets/mailer/api-user-recover.png +0 -0
  578. package/src/client/public/default/browserconfig.xml +12 -0
  579. package/src/client/public/default/favicon-16x16.png +0 -0
  580. package/src/client/public/default/favicon-32x32.png +0 -0
  581. package/src/client/public/default/favicon-48x48.png +0 -0
  582. package/src/client/public/default/favicon.ico +0 -0
  583. package/src/client/public/default/manifest.webmanifest +69 -0
  584. package/src/client/public/default/mstile-144x144.png +0 -0
  585. package/src/client/public/default/mstile-150x150.png +0 -0
  586. package/src/client/public/default/mstile-310x150.png +0 -0
  587. package/src/client/public/default/mstile-310x310.png +0 -0
  588. package/src/client/public/default/mstile-70x70.png +0 -0
  589. package/src/client/public/default/safari-pinned-tab.svg +24 -0
  590. package/src/client/public/default/site.webmanifest +69 -0
  591. package/src/client/public/default/sitemap +148 -0
  592. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  593. package/src/client/public/default/yandex-browser-manifest.json +9 -0
  594. package/src/client/public/doc/favicon.ico +0 -0
  595. package/src/client/public/doc/sitemap +148 -0
  596. package/src/client/public/itemledger/android-chrome-144x144.png +0 -0
  597. package/src/client/public/itemledger/android-chrome-192x192.png +0 -0
  598. package/src/client/public/itemledger/android-chrome-256x256.png +0 -0
  599. package/src/client/public/itemledger/android-chrome-36x36.png +0 -0
  600. package/src/client/public/itemledger/android-chrome-384x384.png +0 -0
  601. package/src/client/public/itemledger/android-chrome-48x48.png +0 -0
  602. package/src/client/public/itemledger/android-chrome-512x512.png +0 -0
  603. package/src/client/public/itemledger/android-chrome-72x72.png +0 -0
  604. package/src/client/public/itemledger/android-chrome-96x96.png +0 -0
  605. package/src/client/public/itemledger/apple-touch-icon-1024x1024.png +0 -0
  606. package/src/client/public/itemledger/apple-touch-icon-114x114.png +0 -0
  607. package/src/client/public/itemledger/apple-touch-icon-120x120.png +0 -0
  608. package/src/client/public/itemledger/apple-touch-icon-144x144.png +0 -0
  609. package/src/client/public/itemledger/apple-touch-icon-152x152.png +0 -0
  610. package/src/client/public/itemledger/apple-touch-icon-167x167.png +0 -0
  611. package/src/client/public/itemledger/apple-touch-icon-180x180.png +0 -0
  612. package/src/client/public/itemledger/apple-touch-icon-57x57.png +0 -0
  613. package/src/client/public/itemledger/apple-touch-icon-60x60.png +0 -0
  614. package/src/client/public/itemledger/apple-touch-icon-72x72.png +0 -0
  615. package/src/client/public/itemledger/apple-touch-icon-76x76.png +0 -0
  616. package/src/client/public/itemledger/apple-touch-icon-precomposed.png +0 -0
  617. package/src/client/public/itemledger/apple-touch-icon.png +0 -0
  618. package/src/client/public/itemledger/apple-touch-startup-image-1125x2436.png +0 -0
  619. package/src/client/public/itemledger/apple-touch-startup-image-1136x640.png +0 -0
  620. package/src/client/public/itemledger/apple-touch-startup-image-1170x2532.png +0 -0
  621. package/src/client/public/itemledger/apple-touch-startup-image-1179x2556.png +0 -0
  622. package/src/client/public/itemledger/apple-touch-startup-image-1242x2208.png +0 -0
  623. package/src/client/public/itemledger/apple-touch-startup-image-1242x2688.png +0 -0
  624. package/src/client/public/itemledger/apple-touch-startup-image-1284x2778.png +0 -0
  625. package/src/client/public/itemledger/apple-touch-startup-image-1290x2796.png +0 -0
  626. package/src/client/public/itemledger/apple-touch-startup-image-1334x750.png +0 -0
  627. package/src/client/public/itemledger/apple-touch-startup-image-1488x2266.png +0 -0
  628. package/src/client/public/itemledger/apple-touch-startup-image-1536x2048.png +0 -0
  629. package/src/client/public/itemledger/apple-touch-startup-image-1620x2160.png +0 -0
  630. package/src/client/public/itemledger/apple-touch-startup-image-1640x2160.png +0 -0
  631. package/src/client/public/itemledger/apple-touch-startup-image-1668x2224.png +0 -0
  632. package/src/client/public/itemledger/apple-touch-startup-image-1668x2388.png +0 -0
  633. package/src/client/public/itemledger/apple-touch-startup-image-1792x828.png +0 -0
  634. package/src/client/public/itemledger/apple-touch-startup-image-2048x1536.png +0 -0
  635. package/src/client/public/itemledger/apple-touch-startup-image-2048x2732.png +0 -0
  636. package/src/client/public/itemledger/apple-touch-startup-image-2160x1620.png +0 -0
  637. package/src/client/public/itemledger/apple-touch-startup-image-2160x1640.png +0 -0
  638. package/src/client/public/itemledger/apple-touch-startup-image-2208x1242.png +0 -0
  639. package/src/client/public/itemledger/apple-touch-startup-image-2224x1668.png +0 -0
  640. package/src/client/public/itemledger/apple-touch-startup-image-2266x1488.png +0 -0
  641. package/src/client/public/itemledger/apple-touch-startup-image-2388x1668.png +0 -0
  642. package/src/client/public/itemledger/apple-touch-startup-image-2436x1125.png +0 -0
  643. package/src/client/public/itemledger/apple-touch-startup-image-2532x1170.png +0 -0
  644. package/src/client/public/itemledger/apple-touch-startup-image-2556x1179.png +0 -0
  645. package/src/client/public/itemledger/apple-touch-startup-image-2688x1242.png +0 -0
  646. package/src/client/public/itemledger/apple-touch-startup-image-2732x2048.png +0 -0
  647. package/src/client/public/itemledger/apple-touch-startup-image-2778x1284.png +0 -0
  648. package/src/client/public/itemledger/apple-touch-startup-image-2796x1290.png +0 -0
  649. package/src/client/public/itemledger/apple-touch-startup-image-640x1136.png +0 -0
  650. package/src/client/public/itemledger/apple-touch-startup-image-750x1334.png +0 -0
  651. package/src/client/public/itemledger/apple-touch-startup-image-828x1792.png +0 -0
  652. package/src/client/public/itemledger/assets/logo/base-icon.png +0 -0
  653. package/src/client/public/itemledger/browserconfig.xml +12 -0
  654. package/src/client/public/itemledger/favicon-16x16.png +0 -0
  655. package/src/client/public/itemledger/favicon-32x32.png +0 -0
  656. package/src/client/public/itemledger/favicon-48x48.png +0 -0
  657. package/src/client/public/itemledger/favicon.ico +0 -0
  658. package/src/client/public/itemledger/manifest.webmanifest +69 -0
  659. package/src/client/public/itemledger/microdata.json +71 -0
  660. package/src/client/public/itemledger/mstile-144x144.png +0 -0
  661. package/src/client/public/itemledger/mstile-150x150.png +0 -0
  662. package/src/client/public/itemledger/mstile-310x150.png +0 -0
  663. package/src/client/public/itemledger/mstile-310x310.png +0 -0
  664. package/src/client/public/itemledger/mstile-70x70.png +0 -0
  665. package/src/client/public/itemledger/sitemap +148 -0
  666. package/src/client/public/itemledger/yandex-browser-50x50.png +0 -0
  667. package/src/client/public/itemledger/yandex-browser-manifest.json +9 -0
  668. package/src/client/public/test/favicon.ico +0 -0
  669. package/src/client/public/test/sitemap +148 -0
  670. package/src/client/services/atlas-sprite-sheet/atlas-sprite-sheet.service.js +137 -0
  671. package/src/client/services/core/core.service.js +309 -0
  672. package/src/client/services/crypto/crypto.service.js +68 -0
  673. package/src/client/services/cyberia-action/cyberia-action.service.js +99 -0
  674. package/src/client/services/cyberia-client-hints/cyberia-client-hints.service.js +99 -0
  675. package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +99 -0
  676. package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
  677. package/src/client/services/cyberia-entity/cyberia-entity.service.js +99 -0
  678. package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +99 -0
  679. package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
  680. package/src/client/services/cyberia-instance/cyberia-instance.service.js +137 -0
  681. package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +99 -0
  682. package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
  683. package/src/client/services/cyberia-map/cyberia-map.service.js +120 -0
  684. package/src/client/services/cyberia-quest/cyberia-quest.service.js +99 -0
  685. package/src/client/services/cyberia-quest-progress/cyberia-quest-progress.service.js +99 -0
  686. package/src/client/services/cyberia-saga/cyberia-saga.service.js +99 -0
  687. package/src/client/services/cyberia-skill/cyberia-skill.service.js +99 -0
  688. package/src/client/services/default/default.management.js +1015 -0
  689. package/src/client/services/default/default.service.js +99 -0
  690. package/src/client/services/document/document.service.js +134 -0
  691. package/src/client/services/file/file.service.js +94 -0
  692. package/src/client/services/instance/instance.management.js +78 -0
  693. package/src/client/services/instance/instance.service.js +107 -0
  694. package/src/client/services/ipfs/ipfs.service.js +118 -0
  695. package/src/client/services/object-layer/object-layer.management.js +414 -0
  696. package/src/client/services/object-layer/object-layer.service.js +208 -0
  697. package/src/client/services/object-layer-render-frames/object-layer-render-frames.service.js +99 -0
  698. package/src/client/services/test/test.service.js +68 -0
  699. package/src/client/services/user/guest.service.js +86 -0
  700. package/src/client/services/user/user.management.js +51 -0
  701. package/src/client/services/user/user.service.js +106 -0
  702. package/src/client/ssr/RootDocument.js +237 -0
  703. package/src/client/ssr/body/404.js +77 -0
  704. package/src/client/ssr/body/500.js +76 -0
  705. package/src/client/ssr/body/CacheControl.js +117 -0
  706. package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +97 -0
  707. package/src/client/ssr/body/DefaultSplashScreen.js +97 -0
  708. package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
  709. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +90 -0
  710. package/src/client/ssr/head/CryptokoynScripts.js +4 -0
  711. package/src/client/ssr/head/Css.js +241 -0
  712. package/src/client/ssr/head/CyberiaPortalScripts.js +6 -0
  713. package/src/client/ssr/head/DefaultScripts.js +6 -0
  714. package/src/client/ssr/head/ItemledgerScripts.js +4 -0
  715. package/src/client/ssr/head/Microdata.js +11 -0
  716. package/src/client/ssr/head/Production.js +1 -0
  717. package/src/client/ssr/head/Pwa.js +146 -0
  718. package/src/client/ssr/head/PwaItemledger.js +197 -0
  719. package/src/client/ssr/head/Seo.js +15 -0
  720. package/src/client/ssr/head/UnderpostScripts.js +6 -0
  721. package/src/client/ssr/mailer/DefaultRecoverEmail.js +20 -0
  722. package/src/client/ssr/mailer/DefaultVerifyEmail.js +16 -0
  723. package/src/client/ssr/views/Cyberia404.js +328 -0
  724. package/src/client/ssr/views/CyberiaServerMetrics.js +1070 -0
  725. package/src/client/ssr/views/Maintenance.js +64 -0
  726. package/src/client/ssr/views/NoNetworkConnection.js +68 -0
  727. package/src/client/ssr/views/Test.js +199 -0
  728. package/src/client/sw/core.sw.js +274 -0
  729. package/src/client-builder/client-build-docs.js +493 -0
  730. package/src/client-builder/client-build-live.js +100 -0
  731. package/src/client-builder/client-build.js +1092 -0
  732. package/src/client-builder/client-dev-server.js +88 -0
  733. package/src/client-builder/client-formatted.js +170 -0
  734. package/src/client-builder/client-icons.js +108 -0
  735. package/src/client-builder/ssr.js +124 -0
  736. package/src/client.build.js +17 -0
  737. package/src/client.dev.js +21 -0
  738. package/src/db/DataBaseProvider.js +213 -0
  739. package/src/db/mariadb/MariaDB.js +72 -0
  740. package/src/db/mongo/MongoBootstrap.js +657 -0
  741. package/src/db/mongo/MongooseDB.js +199 -0
  742. package/src/grpc/cyberia/grpc-server.js +162 -0
  743. package/src/index.js +357 -0
  744. package/src/mailer/EmailRender.js +116 -0
  745. package/src/mailer/MailerProvider.js +213 -0
  746. package/src/projects/cyberia/atlas-sprite-sheet-generator.js +413 -0
  747. package/src/projects/cyberia/besu-genesis-generator.js +1630 -0
  748. package/src/projects/cyberia/catalog-cyberia.js +90 -0
  749. package/src/projects/cyberia/gemini-client.js +175 -0
  750. package/src/projects/cyberia/generate-saga.js +2137 -0
  751. package/src/projects/cyberia/hot-reload-trigger.js +163 -0
  752. package/src/projects/cyberia/instance-data.js +719 -0
  753. package/src/projects/cyberia/ipfs-client.js +599 -0
  754. package/src/projects/cyberia/map-preview-generator.js +304 -0
  755. package/src/projects/cyberia/object-layer.js +978 -0
  756. package/src/projects/cyberia/semantic-layer-generator-floor.js +319 -0
  757. package/src/projects/cyberia/semantic-layer-generator-resource.js +259 -0
  758. package/src/projects/cyberia/semantic-layer-generator-skin.js +1164 -0
  759. package/src/projects/cyberia/semantic-layer-generator.js +753 -0
  760. package/src/projects/cyberia/shape-generator.js +1060 -0
  761. package/src/projects/underpost/catalog-underpost.js +60 -0
  762. package/src/proxy.js +19 -0
  763. package/src/runtime/cyberia-client/Dockerfile +49 -0
  764. package/src/runtime/cyberia-client/Dockerfile.dev +75 -0
  765. package/src/runtime/cyberia-server/Dockerfile +43 -0
  766. package/src/runtime/cyberia-server/Dockerfile.dev +56 -0
  767. package/src/runtime/engine-cyberia/Dockerfile +161 -0
  768. package/src/runtime/engine-cyberia/Dockerfile.dev +161 -0
  769. package/src/runtime/engine-cyberia/Dockerfile.test +165 -0
  770. package/src/runtime/engine-cyberia/compose.env +144 -0
  771. package/src/runtime/engine-cyberia/docker-compose.yml +434 -0
  772. package/src/runtime/engine-cyberia/ipfs/configure-ipfs.sh +13 -0
  773. package/src/runtime/engine-cyberia/mongodb/entrypoint.sh +76 -0
  774. package/src/runtime/engine-cyberia/nginx.conf +128 -0
  775. package/src/runtime/express/Dockerfile +45 -0
  776. package/src/runtime/express/Express.js +285 -0
  777. package/src/runtime/lampp/Dockerfile +62 -0
  778. package/src/runtime/lampp/Lampp.js +359 -0
  779. package/src/runtime/nginx/Nginx.js +250 -0
  780. package/src/runtime/wp/Dockerfile +62 -0
  781. package/src/runtime/wp/Wp.js +642 -0
  782. package/src/server/auth.js +713 -0
  783. package/src/server/backup.js +102 -0
  784. package/src/server/catalog.js +72 -0
  785. package/src/server/conf.js +2316 -0
  786. package/src/server/cron.js +476 -0
  787. package/src/server/crypto.js +210 -0
  788. package/src/server/data-query.js +461 -0
  789. package/src/server/dns.js +553 -0
  790. package/src/server/downloader.js +73 -0
  791. package/src/server/logger.js +229 -0
  792. package/src/server/middlewares.js +152 -0
  793. package/src/server/peer.js +75 -0
  794. package/src/server/process.js +299 -0
  795. package/src/server/proxy.js +139 -0
  796. package/src/server/runtime-status.js +252 -0
  797. package/src/server/runtime.js +183 -0
  798. package/src/server/start.js +272 -0
  799. package/src/server/tls.js +254 -0
  800. package/src/server/valkey.js +201 -0
  801. package/src/server.js +25 -0
  802. package/src/ws/IoInterface.js +129 -0
  803. package/src/ws/IoServer.js +68 -0
  804. package/src/ws/core/channels/core.ws.chat.js +68 -0
  805. package/src/ws/core/channels/core.ws.mailer.js +116 -0
  806. package/src/ws/core/channels/core.ws.stream.js +90 -0
  807. package/src/ws/core/core.ws.connection.js +41 -0
  808. package/src/ws/core/core.ws.emit.js +37 -0
  809. package/src/ws/core/core.ws.server.js +44 -0
  810. package/src/ws/default/channels/default.ws.main.js +57 -0
  811. package/src/ws/default/default.ws.connection.js +35 -0
  812. package/src/ws/default/default.ws.emit.js +14 -0
  813. package/src/ws/default/default.ws.server.js +39 -0
  814. package/test/api.test.js +53 -0
  815. package/test/crypto.test.js +117 -0
  816. package/test/cyberia-instance-conf-defaults.test.js +140 -0
  817. package/test/deploy-monitor.test.js +267 -0
  818. package/test/shape-generator.test.js +463 -0
  819. package/tsconfig.docs.json +15 -0
  820. package/typedoc.dd-cyberia.json +31 -0
  821. package/typedoc.json +31 -0
@@ -0,0 +1,978 @@
1
+ /**
2
+ * Provides utilities and engine logic for processing and managing Cyberia Online's object layer assets (skins, floors, weapons, etc.).
3
+ * Shared logic consumed by both the Cyberia CLI and the REST API service layer.
4
+ * @module src/projects/cyberia/object-layer.js
5
+ * @namespace CyberiaObjectLayer
6
+ */
7
+
8
+ import fs from 'fs-extra';
9
+ import path from 'path';
10
+ import { PNG } from 'pngjs';
11
+ import sharp from 'sharp';
12
+ import { Jimp, intToRGBA, rgbaToInt } from 'jimp';
13
+ import crypto from 'crypto';
14
+ import stringify from 'fast-json-stable-stringify';
15
+
16
+ import { range } from '../../client/components/core/CommonJs.js';
17
+ import {
18
+ generateRandomStats,
19
+ getKeyframeDirectionsByCode,
20
+ OBJECT_LAYER_DIRECTION_NAME_TO_CODE,
21
+ } from '../../client/components/cyberia/SharedDefaultsCyberia.js';
22
+ import { loggerFactory } from '../../server/logger.js';
23
+
24
+ const logger = loggerFactory(import.meta);
25
+
26
+ /**
27
+ * @typedef {Object} ObjectLayerCallbackPayload
28
+ * @property {string} path - The full file path to the image.
29
+ * @property {string} objectLayerType - The type of object layer (e.g., 'skin', 'floor').
30
+ * @property {string} objectLayerId - The unique ID of the object layer asset.
31
+ * @property {string} direction - The direction folder name (e.g., '08', '12').
32
+ * @property {string} frame - The frame file name.
33
+ * @memberof CyberiaObjectLayer
34
+ */
35
+
36
+ /**
37
+ * @typedef {Object} ObjectLayerRenderFramesData
38
+ * @property {Object<string, number[][][]>} frames - Map of direction names to arrays of frame matrices.
39
+ * @property {Array<number[]>} colors - Global color palette shared across all frames.
40
+ * @property {number} frame_duration - Duration of each frame in milliseconds.
41
+ * @memberof CyberiaObjectLayer
42
+ */
43
+
44
+ /**
45
+ * @typedef {Object} ObjectLayerData
46
+ * @property {Object} data - Object layer data payload.
47
+ * @property {Object} data.item - Item descriptor.
48
+ * @property {string} data.item.id - Unique identifier for the item.
49
+ * @property {string} data.item.type - Type of the item (e.g., 'skin', 'floor').
50
+ * @property {string} [data.item.description] - Human-readable description.
51
+ * @property {boolean} [data.item.activable] - Whether the item can be activated.
52
+ * @property {Object} data.stats - Statistical attributes of the object layer.
53
+ * @property {Object} [data.render] - IPFS content identifiers for the consolidated atlas sprite sheet.
54
+ * @property {string} [data.render.cid] - IPFS CID for the consolidated atlas sprite sheet PNG.
55
+ * @property {string} [data.render.metadataCid] - IPFS CID for the atlas sprite sheet metadata JSON (fast-json-stable-stringify).
56
+ * @property {ObjectLayerRenderFramesData} [objectLayerRenderFramesData] - Render frames data (transient, used before persisting).
57
+ * @property {import('mongoose').Types.ObjectId} [objectLayerRenderFramesId] - Reference to persisted ObjectLayerRenderFrames document.
58
+ * @property {string} [sha256] - SHA-256 hash of the object layer data.
59
+ * @memberof CyberiaObjectLayer
60
+ */
61
+
62
+ /**
63
+ * @typedef {Object} BuildFromDirectoryResult
64
+ * @property {ObjectLayerRenderFramesData} objectLayerRenderFramesData - The assembled render frames data.
65
+ * @property {Object} objectLayerData - The assembled object layer data (without render frames reference or sha256).
66
+ * @memberof CyberiaObjectLayer
67
+ */
68
+
69
+ /**
70
+ * @typedef {Object} CreateDocumentsOptions
71
+ * @property {boolean} [generateAtlas=true] - Whether to generate the atlas sprite sheet after creating documents.
72
+ * @property {Object} [atlasServiceContext] - Context required by AtlasSpriteSheetService.generate (req, res, options).
73
+ * @property {Object} [atlasServiceContext.req] - Express-like request object (must include auth).
74
+ * @property {Object} [atlasServiceContext.res] - Express-like response object.
75
+ * @property {Object} [atlasServiceContext.options] - Server options (host, path).
76
+ * @memberof CyberiaObjectLayer
77
+ */
78
+
79
+ /**
80
+ * @typedef {Object} CreateDocumentsResult
81
+ * @property {Object} objectLayer - The persisted ObjectLayer mongoose document.
82
+ * @property {Object} objectLayerRenderFramesDoc - The persisted ObjectLayerRenderFrames mongoose document.
83
+ * @memberof CyberiaObjectLayer
84
+ */
85
+
86
+ /**
87
+ * Engine class providing static utilities for Cyberia Online object layer asset processing,
88
+ * frame extraction, directory iteration, image building, and document creation logic.
89
+ * @class ObjectLayerEngine
90
+ * @memberof CyberiaObjectLayer
91
+ */
92
+ export class ObjectLayerEngine {
93
+ /**
94
+ * Iterates through the directory structure of object layer PNG assets for a given type.
95
+ * Walks `./src/client/public/cyberia/assets/{objectLayerType}/{id}/{direction}/{frame}`.
96
+ * @static
97
+ * @param {string} [objectLayerType='skin'] - The type of object layer to iterate over (e.g., 'skin', 'floor').
98
+ * @param {function(ObjectLayerCallbackPayload): Promise<void>} [callback=() => {}] - The async function to execute for each image file found.
99
+ * @returns {Promise<void>}
100
+ * @memberof CyberiaObjectLayer
101
+ */
102
+ static async pngDirectoryIteratorByObjectLayerType(
103
+ objectLayerType = 'skin',
104
+ callback = ({ path, objectLayerType, objectLayerId, direction, frame }) => {},
105
+ ) {
106
+ const assetRoot = `./src/client/public/cyberia/assets/${objectLayerType}`;
107
+ if (!fs.existsSync(assetRoot)) {
108
+ logger.warn(`Asset root not found for type: ${objectLayerType}`);
109
+ return;
110
+ }
111
+
112
+ for (const objectLayerId of await fs.readdir(assetRoot)) {
113
+ const idPath = `${assetRoot}/${objectLayerId}`;
114
+ if (!fs.statSync(idPath).isDirectory()) continue;
115
+
116
+ for (const direction of await fs.readdir(idPath)) {
117
+ const dirFolder = `${idPath}/${direction}`;
118
+ if (!fs.statSync(dirFolder).isDirectory()) continue;
119
+
120
+ for (const frame of await fs.readdir(dirFolder)) {
121
+ const imageFilePath = `${dirFolder}/${frame}`;
122
+ await callback({ path: imageFilePath, objectLayerType, objectLayerId, direction, frame });
123
+ }
124
+ }
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Asynchronously reads a PNG file and resolves with its raw bitmap data, width, and height.
130
+ * @static
131
+ * @param {string} filePath - The path to the PNG file.
132
+ * @returns {Promise<{width: number, height: number, data: Buffer} | {error: true, message: string}>} The image data or an error object.
133
+ * @memberof CyberiaObjectLayer
134
+ */
135
+ static readPngAsync(filePath) {
136
+ return new Promise((resolve, reject) => {
137
+ fs.createReadStream(filePath)
138
+ .pipe(new PNG())
139
+ .on('parsed', function () {
140
+ resolve({
141
+ width: this.width,
142
+ height: this.height,
143
+ data: Buffer.from(this.data),
144
+ });
145
+ })
146
+ .on('error', (error) => {
147
+ logger.error(`Error reading PNG file: ${filePath}`, error);
148
+ // Resolve with a specific error indicator instead of rejecting
149
+ resolve({ error: true, message: error.message });
150
+ });
151
+ });
152
+ }
153
+
154
+ /**
155
+ * Processes an image file (PNG or GIF) to generate a frame matrix and a color palette (map_color).
156
+ * It quantizes the image based on a factor derived from image height (mazeFactor).
157
+ * @static
158
+ * @param {string} path - The path to the image file.
159
+ * @param {Array<number[]>} [colors=[]] - The existing color palette array to append new colors to.
160
+ * @returns {Promise<{frame: number[][], colors: Array<number[]>}>} The frame matrix and the updated color palette.
161
+ * @memberof CyberiaObjectLayer
162
+ */
163
+ static async frameFactory(path, colors = []) {
164
+ const frame = [];
165
+ try {
166
+ let image;
167
+
168
+ if (path.endsWith('.gif')) {
169
+ image = await Jimp.read(path);
170
+ // remove gif file
171
+ fs.removeSync(path);
172
+ // save image replacing gif for png
173
+ const pngPath = path.replace('.gif', '.png');
174
+ await image.write(pngPath);
175
+ } else {
176
+ const png = await ObjectLayerEngine.readPngAsync(path);
177
+ if (png.error) {
178
+ throw new Error(`Failed to read PNG: ${png.message}`);
179
+ }
180
+ image = new Jimp(png);
181
+ }
182
+
183
+ const cellSize = parseInt(image.bitmap.height / 24);
184
+ let matrixY = -1;
185
+ for (const y of range(0, image.bitmap.height - 1)) {
186
+ if (y % cellSize === 0) {
187
+ matrixY++;
188
+ if (!frame[matrixY]) frame[matrixY] = [];
189
+ }
190
+ let matrixX = -1;
191
+ for (const x of range(0, image.bitmap.width - 1)) {
192
+ const rgba = Object.values(intToRGBA(image.getPixelColor(x, y)));
193
+ if (y % cellSize === 0 && x % cellSize === 0) {
194
+ matrixX++;
195
+ const colorIndex = colors.findIndex(
196
+ (c) => c[0] === rgba[0] && c[1] === rgba[1] && c[2] === rgba[2] && c[3] === rgba[3],
197
+ );
198
+ if (colorIndex === -1) {
199
+ colors.push(rgba);
200
+ frame[matrixY][matrixX] = colors.length - 1;
201
+ } else {
202
+ frame[matrixY][matrixX] = colorIndex;
203
+ }
204
+ }
205
+ }
206
+ }
207
+ } catch (error) {
208
+ logger.error(`Failed to process image ${path}:`, error);
209
+ }
210
+ return { frame, colors };
211
+ }
212
+
213
+ /**
214
+ * Processes an image file through {@link ObjectLayerEngine.frameFactory} and adds the resulting frame to the render data structure.
215
+ * Updates the color palette and pushes the frame to all keyframe directions corresponding to the given direction code.
216
+ * Initializes colors array, frames object, and direction arrays if they don't exist.
217
+ * @static
218
+ * @param {ObjectLayerRenderFramesData} objectLayerRenderFramesData - The render data object containing frames and colors.
219
+ * @param {string} imagePath - The path to the image file to process.
220
+ * @param {string} directionCode - The numerical direction code (e.g., '08', '14').
221
+ * @returns {Promise<ObjectLayerRenderFramesData>} The updated render data object.
222
+ * @memberof CyberiaObjectLayer
223
+ */
224
+ static async processAndPushFrame(objectLayerRenderFramesData, imagePath, directionCode) {
225
+ // Initialize colors array if it doesn't exist
226
+ if (!objectLayerRenderFramesData.colors) {
227
+ objectLayerRenderFramesData.colors = [];
228
+ }
229
+
230
+ // Initialize frames object if it doesn't exist
231
+ if (!objectLayerRenderFramesData.frames) {
232
+ objectLayerRenderFramesData.frames = {};
233
+ }
234
+
235
+ // Process the image and extract frame matrix and updated colors
236
+ const processedObjectLayerRenderFramesData = await ObjectLayerEngine.frameFactory(
237
+ imagePath,
238
+ objectLayerRenderFramesData.colors,
239
+ );
240
+
241
+ // Update the colors palette
242
+ objectLayerRenderFramesData.colors = processedObjectLayerRenderFramesData.colors;
243
+
244
+ // Get all keyframe directions for this direction code
245
+ const keyframeDirections = getKeyframeDirectionsByCode(directionCode);
246
+
247
+ // Push the frame to all corresponding directions
248
+ for (const keyframeDirection of keyframeDirections) {
249
+ if (!objectLayerRenderFramesData.frames[keyframeDirection]) {
250
+ objectLayerRenderFramesData.frames[keyframeDirection] = [];
251
+ }
252
+ objectLayerRenderFramesData.frames[keyframeDirection].push(processedObjectLayerRenderFramesData.frame);
253
+ }
254
+
255
+ return objectLayerRenderFramesData;
256
+ }
257
+
258
+ /**
259
+ * Builds a PNG image file from a tile matrix and color map using Jimp and Sharp.
260
+ * @static
261
+ * @param {Object} options - Options object.
262
+ * @param {Object} options.tile - The tile data.
263
+ * @param {Array<number[]>} options.tile.map_color - The color palette.
264
+ * @param {number[][]} options.tile.frame_matrix - The matrix of color indices.
265
+ * @param {string} options.imagePath - The output path for the generated image.
266
+ * @param {number} [options.cellPixelDim=20] - The pixel dimension of each cell in the matrix.
267
+ * @param {function(number, number, number[]): number} [options.opacityFilter] - Function to filter opacity (ignored in this implementation).
268
+ * @returns {Promise<void>}
269
+ * @memberof CyberiaObjectLayer
270
+ */
271
+ static async buildImgFromTile(
272
+ options = {
273
+ tile: { map_color: null, frame_matrix: null },
274
+ imagePath: '',
275
+ cellPixelDim: 20,
276
+ opacityFilter: (x, y, color) => 255,
277
+ },
278
+ ) {
279
+ const { tile, imagePath, cellPixelDim } = options;
280
+ const frameMatrix = tile.frame_matrix;
281
+ if (!frameMatrix || frameMatrix.length === 0 || frameMatrix[0].length === 0) {
282
+ logger.error(`Cannot build image from empty or invalid frame_matrix for path: ${imagePath}`);
283
+ return;
284
+ }
285
+
286
+ const sharpOptions = {
287
+ create: {
288
+ width: cellPixelDim * frameMatrix[0].length,
289
+ height: cellPixelDim * frameMatrix.length,
290
+ channels: 4,
291
+ background: { r: 0, g: 0, b: 0, alpha: 0 }, // transparent background
292
+ },
293
+ };
294
+
295
+ let image = await sharp(sharpOptions).png().toBuffer();
296
+ fs.writeFileSync(imagePath, image);
297
+ image = await Jimp.read(imagePath);
298
+
299
+ for (let y = 0; y < frameMatrix.length; y++) {
300
+ for (let x = 0; x < frameMatrix[y].length; x++) {
301
+ const colorIndex = frameMatrix[y][x];
302
+ if (colorIndex === null || colorIndex === undefined) continue;
303
+
304
+ const color = tile.map_color[colorIndex];
305
+ if (!color) continue;
306
+
307
+ const rgbaColor = color.length === 4 ? color : [...color, 255]; // Ensure alpha channel
308
+
309
+ for (let dy = 0; dy < cellPixelDim; dy++) {
310
+ for (let dx = 0; dx < cellPixelDim; dx++) {
311
+ const pixelX = x * cellPixelDim + dx;
312
+ const pixelY = y * cellPixelDim + dy;
313
+ image.setPixelColor(rgbaToInt(...rgbaColor), pixelX, pixelY);
314
+ }
315
+ }
316
+ }
317
+ }
318
+
319
+ await image.write(imagePath);
320
+ }
321
+
322
+ // ──────────────────────────────────────────────────────────────────────────
323
+ // Document lifecycle methods
324
+ // ──────────────────────────────────────────────────────────────────────────
325
+
326
+ /**
327
+ * Scans a local asset directory for PNG frame images and assembles both
328
+ * {@link ObjectLayerRenderFramesData} and {@link ObjectLayerData} from the directory contents
329
+ * and an optional `metadata.json` file.
330
+ *
331
+ * This is the shared first step consumed by both the Cyberia CLI `--import` flow
332
+ * and the REST API service `post` / `put` `/metadata` endpoints.
333
+ *
334
+ * @static
335
+ * @param {Object} params - Parameters.
336
+ * @param {string} params.folder - Absolute or relative path to the asset folder
337
+ * (e.g., `./src/client/public/cyberia/assets/skin/myskin`). Must contain numeric
338
+ * direction sub-folders (`08`, `18`, …) with PNG frame files.
339
+ * @param {string} params.objectLayerType - The item type string (e.g., 'skin', 'floor').
340
+ * @param {string} params.objectLayerId - The item id string.
341
+ * @param {Object} [params.metadataOverride=null] - When provided, used as the authoritative
342
+ * metadata instead of reading `metadata.json` from disk. The REST API passes `req.body`
343
+ * here; the CLI passes `null` so the file is read from disk.
344
+ * @returns {Promise<BuildFromDirectoryResult>} The assembled render frames data and object layer data.
345
+ * @memberof CyberiaObjectLayer
346
+ */
347
+ static async buildObjectLayerDataFromDirectory({ folder, objectLayerType, objectLayerId, metadataOverride = null }) {
348
+ let metadata = metadataOverride;
349
+
350
+ // If no override was supplied, try to read metadata.json from the folder
351
+ if (!metadata) {
352
+ const metadataPath = `${folder}/metadata.json`;
353
+ if (fs.existsSync(metadataPath)) {
354
+ metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
355
+ }
356
+ }
357
+
358
+ // Build objectLayerRenderFramesData
359
+ let objectLayerRenderFramesData;
360
+ if (metadata && metadata.objectLayerRenderFramesData) {
361
+ objectLayerRenderFramesData = {
362
+ frame_duration: metadata.objectLayerRenderFramesData.frame_duration || 250,
363
+ frames: {},
364
+ colors: [],
365
+ };
366
+ } else if (metadata && metadata.data && metadata.data.render) {
367
+ objectLayerRenderFramesData = {
368
+ frame_duration: metadata.data.render.frame_duration || 250,
369
+ frames: {},
370
+ colors: [],
371
+ };
372
+ } else {
373
+ objectLayerRenderFramesData = {
374
+ frame_duration: 250,
375
+ frames: {},
376
+ colors: [],
377
+ };
378
+ }
379
+
380
+ // Build objectLayerData
381
+ let objectLayerData;
382
+ if (metadata && metadata.data) {
383
+ objectLayerData = {
384
+ data: {
385
+ item: metadata.data.item || {
386
+ id: objectLayerId,
387
+ type: objectLayerType,
388
+ description: '',
389
+ activable: true,
390
+ },
391
+ stats: metadata.data.stats || generateRandomStats(),
392
+ ledger: metadata.data.ledger || { type: 'OFF_CHAIN' },
393
+ },
394
+ };
395
+ } else {
396
+ objectLayerData = {
397
+ data: {
398
+ item: {
399
+ id: objectLayerId,
400
+ type: objectLayerType,
401
+ description: '',
402
+ activable: true,
403
+ },
404
+ stats: generateRandomStats(),
405
+ ledger: { type: 'OFF_CHAIN' },
406
+ },
407
+ };
408
+ }
409
+
410
+ // Process all PNG files from direction sub-folders
411
+ if (fs.existsSync(folder)) {
412
+ const directionFolders = await fs.readdir(folder);
413
+ for (const directionCode of directionFolders) {
414
+ const directionPath = `${folder}/${directionCode}`;
415
+
416
+ // Skip non-directories (metadata.json, etc.)
417
+ try {
418
+ const stat = await fs.stat(directionPath);
419
+ if (!stat.isDirectory()) continue;
420
+ } catch (error) {
421
+ logger.warn(`Skipping ${directionCode}: ${error.message}`);
422
+ continue;
423
+ }
424
+
425
+ const frameFiles = await fs.readdir(directionPath);
426
+ // Sort frame files numerically
427
+ frameFiles.sort((a, b) => {
428
+ const numA = parseInt(a.split('.')[0]);
429
+ const numB = parseInt(b.split('.')[0]);
430
+ return numA - numB;
431
+ });
432
+
433
+ for (const frameFile of frameFiles) {
434
+ if (!frameFile.endsWith('.png')) continue;
435
+
436
+ const framePath = `${directionPath}/${frameFile}`;
437
+ await ObjectLayerEngine.processAndPushFrame(objectLayerRenderFramesData, framePath, directionCode);
438
+ }
439
+ }
440
+ }
441
+
442
+ return { objectLayerRenderFramesData, objectLayerData };
443
+ }
444
+
445
+ /**
446
+ * Computes a SHA-256 hash of the given object layer data using deterministic JSON serialisation.
447
+ * @static
448
+ * @param {Object} data - The `data` sub-document of an ObjectLayer (item, stats, render).
449
+ * @returns {string} Hex-encoded SHA-256 hash.
450
+ * @memberof CyberiaObjectLayer
451
+ */
452
+ static computeSha256(data) {
453
+ return crypto.createHash('sha256').update(stringify(data)).digest('hex');
454
+ }
455
+
456
+ /**
457
+ * Writes frame PNGs and an optional metadata.json to one or more base asset
458
+ * directories. This is the shared write-to-disk step consumed by both the
459
+ * Cyberia CLI `--generate` / `--import` flows and the REST API service
460
+ * `post` / `put` `/metadata` endpoints.
461
+ *
462
+ * For each base path the layout produced is:
463
+ * ```
464
+ * {basePath}/assets/{itemType}/{itemId}/{directionCode}/{frameIndex}.png
465
+ * {basePath}/assets/{itemType}/{itemId}/metadata.json (optional)
466
+ * ```
467
+ *
468
+ * @static
469
+ * @param {Object} params
470
+ * @param {string[]} params.basePaths - One or more root paths
471
+ * (e.g. `['./src/client/public/cyberia/', './public/host/path/']`).
472
+ * The conventional `assets/` prefix is appended automatically.
473
+ * @param {string} params.itemType - Object layer type ('floor', 'skin', …).
474
+ * @param {string} params.itemId - Unique item identifier.
475
+ * @param {ObjectLayerRenderFramesData} params.objectLayerRenderFramesData
476
+ * - The render frames data containing `frames`, `colors`,
477
+ * and `frame_duration`.
478
+ * @param {Object} [params.objectLayerData=null] - When provided, a
479
+ * `metadata.json` file is written alongside the frame PNGs.
480
+ * @param {number} [params.cellPixelDim=20] - Pixel size per grid cell.
481
+ * @returns {Promise<string[]>} Flat list of every file path written.
482
+ * @memberof CyberiaObjectLayer
483
+ */
484
+ static async writeStaticFrameAssets({
485
+ basePaths,
486
+ itemType,
487
+ itemId,
488
+ objectLayerRenderFramesData,
489
+ objectLayerData = null,
490
+ cellPixelDim = 20,
491
+ }) {
492
+ const writtenPaths = [];
493
+ const dirToCode = OBJECT_LAYER_DIRECTION_NAME_TO_CODE;
494
+
495
+ for (const basePath of basePaths) {
496
+ // Track which directionCode/frameIndex combos we already wrote for
497
+ // this basePath so duplicate direction names (e.g. down_idle,
498
+ // none_idle, default_idle all map to '08') only write once.
499
+ const written = new Set();
500
+
501
+ for (const [dirName, dirFrames] of Object.entries(objectLayerRenderFramesData.frames)) {
502
+ const code = dirToCode[dirName];
503
+ if (!code) continue;
504
+
505
+ for (let fi = 0; fi < dirFrames.length; fi++) {
506
+ const key = `${code}/${fi}`;
507
+ if (written.has(key)) continue;
508
+ written.add(key);
509
+
510
+ const dirFolder = path.join(basePath, 'assets', itemType, itemId, code);
511
+ await fs.ensureDir(dirFolder);
512
+
513
+ const filePath = path.join(dirFolder, `${fi}.png`);
514
+
515
+ await ObjectLayerEngine.buildImgFromTile({
516
+ tile: {
517
+ map_color: objectLayerRenderFramesData.colors,
518
+ frame_matrix: dirFrames[fi],
519
+ },
520
+ cellPixelDim,
521
+ opacityFilter: (x, y, color) => 255,
522
+ imagePath: filePath,
523
+ });
524
+
525
+ writtenPaths.push(filePath);
526
+ }
527
+ }
528
+
529
+ // Write metadata.json when objectLayerData is supplied
530
+ if (objectLayerData) {
531
+ const metaDir = path.join(basePath, 'assets', itemType, itemId);
532
+ await fs.ensureDir(metaDir);
533
+ const metadataPath = path.join(metaDir, 'metadata.json');
534
+
535
+ await fs.writeJson(
536
+ metadataPath,
537
+ {
538
+ data: objectLayerData.data,
539
+ objectLayerRenderFramesData: {
540
+ frame_duration: objectLayerRenderFramesData.frame_duration,
541
+ },
542
+ generated: true,
543
+ generatorVersion: '1.0.0',
544
+ },
545
+ { spaces: 2 },
546
+ );
547
+ writtenPaths.push(metadataPath);
548
+ }
549
+ }
550
+
551
+ return writtenPaths;
552
+ }
553
+
554
+ /**
555
+ * Creates new ObjectLayerRenderFrames and ObjectLayer documents in MongoDB from the
556
+ * provided data, with cut-over consistency: all CIDs (atlas PNG, atlas metadata, data JSON)
557
+ * are computed and pinned to IPFS BEFORE the ObjectLayer document is created or updated in
558
+ * MongoDB, so the object layer is never visible in queries with empty CIDs.
559
+ *
560
+ * If an existing ObjectLayer with the same `data.item.id` is found, it is atomically
561
+ * replaced (findByIdAndUpdate) and the old ObjectLayerRenderFrames is cleaned up.
562
+ *
563
+ * @static
564
+ * @param {Object} params - Parameters.
565
+ * @param {Object} params.ObjectLayer - Mongoose ObjectLayer model.
566
+ * @param {Object} params.ObjectLayerRenderFrames - Mongoose ObjectLayerRenderFrames model.
567
+ * @param {ObjectLayerRenderFramesData} params.objectLayerRenderFramesData - Render frames payload.
568
+ * @param {Object} params.objectLayerData - Object layer payload (must include `data`).
569
+ * @param {CreateDocumentsOptions} [params.createOptions={}] - Additional options controlling atlas generation and IPFS pinning.
570
+ * @returns {Promise<CreateDocumentsResult>} The persisted documents.
571
+ * @memberof CyberiaObjectLayer
572
+ */
573
+ static async createObjectLayerDocuments({
574
+ ObjectLayer,
575
+ ObjectLayerRenderFrames,
576
+ objectLayerRenderFramesData,
577
+ objectLayerData,
578
+ createOptions = {},
579
+ }) {
580
+ const { generateAtlas = true, atlasServiceContext = null } = createOptions;
581
+
582
+ // 1. Persist ObjectLayerRenderFrames (not queried by the viewer table)
583
+ const objectLayerRenderFramesDoc = await ObjectLayerRenderFrames.create(objectLayerRenderFramesData);
584
+
585
+ // 2. Set up references in memory
586
+ objectLayerData.objectLayerRenderFramesId = objectLayerRenderFramesDoc._id;
587
+ if (!objectLayerData.data.render) objectLayerData.data.render = {};
588
+ objectLayerData.data.render.cid = '';
589
+ objectLayerData.data.render.metadataCid = '';
590
+
591
+ // 3. Stage atlas + IPFS CIDs BEFORE creating/updating the ObjectLayer
592
+ if (generateAtlas && atlasServiceContext) {
593
+ const {
594
+ req,
595
+ res,
596
+ options,
597
+ AtlasSpriteSheetService,
598
+ IpfsClient: ipfsClient,
599
+ createPinRecord,
600
+ } = atlasServiceContext;
601
+
602
+ try {
603
+ const stagingOL = {
604
+ data: objectLayerData.data,
605
+ objectLayerRenderFramesId: objectLayerRenderFramesDoc,
606
+ };
607
+ const result = await AtlasSpriteSheetService.generate(
608
+ { objectLayer: stagingOL, auth: req ? req.auth : undefined },
609
+ res,
610
+ options,
611
+ { skipObjectLayerSave: true },
612
+ );
613
+ objectLayerData.data.render.cid = result.atlasCid;
614
+ objectLayerData.data.render.metadataCid = result.atlasMetadataCid;
615
+ objectLayerData.atlasSpriteSheetId = result.atlasDoc._id;
616
+ } catch (atlasError) {
617
+ logger.error('Failed to generate atlas during staging:', atlasError);
618
+ }
619
+
620
+ // Compute final SHA-256 (includes render CIDs)
621
+ objectLayerData.sha256 = ObjectLayerEngine.computeSha256(objectLayerData.data);
622
+
623
+ // Pin data JSON to IPFS
624
+ if (ipfsClient) {
625
+ try {
626
+ const itemId = objectLayerData.data.item.id;
627
+ const mfsPath = `/object-layer/${itemId}/${itemId}_data.json`;
628
+ const ipfsResult = await ipfsClient.addJsonToIpfs(objectLayerData.data, `${itemId}_data.json`, mfsPath);
629
+ if (ipfsResult) {
630
+ objectLayerData.cid = ipfsResult.cid;
631
+ if (createPinRecord) {
632
+ await createPinRecord({ cid: ipfsResult.cid, resourceType: 'object-layer-data', mfsPath, options });
633
+ }
634
+ }
635
+ } catch (ipfsError) {
636
+ logger.warn('Failed to pin data JSON to IPFS:', ipfsError.message);
637
+ }
638
+ }
639
+ } else {
640
+ // No atlas generation - compute SHA-256 without render CIDs
641
+ objectLayerData.sha256 = ObjectLayerEngine.computeSha256(objectLayerData.data);
642
+ }
643
+
644
+ // 4. Atomic create/upsert - ObjectLayer is fully populated with all CIDs
645
+ let objectLayer;
646
+ const existingByItemId = await ObjectLayer.findOne({ 'data.item.id': objectLayerData.data.item.id });
647
+ if (existingByItemId) {
648
+ const oldRenderFramesId = existingByItemId.objectLayerRenderFramesId;
649
+ logger.info(
650
+ `ObjectLayer for item "${objectLayerData.data.item.id}" exists (${existingByItemId._id}), replacing atomically...`,
651
+ );
652
+ objectLayer = await ObjectLayer.findByIdAndUpdate(existingByItemId._id, objectLayerData, {
653
+ returnDocument: 'after',
654
+ }).populate('objectLayerRenderFramesId');
655
+ if (oldRenderFramesId && !oldRenderFramesId.equals(objectLayerRenderFramesDoc._id)) {
656
+ await ObjectLayerRenderFrames.findByIdAndDelete(oldRenderFramesId);
657
+ }
658
+ } else {
659
+ objectLayer = await (await ObjectLayer.create(objectLayerData)).populate('objectLayerRenderFramesId');
660
+ logger.info(`ObjectLayer created successfully with id: ${objectLayer._id}`);
661
+ }
662
+
663
+ return { objectLayer, objectLayerRenderFramesDoc };
664
+ }
665
+
666
+ /**
667
+ * Updates an existing ObjectLayer and its ObjectLayerRenderFrames from the provided data,
668
+ * with cut-over consistency: a new ObjectLayerRenderFrames is created, then atlas and all
669
+ * CIDs are staged BEFORE the live ObjectLayer is touched. The live document is updated
670
+ * atomically via findByIdAndUpdate only after all CIDs are computed.
671
+ *
672
+ * @static
673
+ * @param {Object} params - Parameters.
674
+ * @param {string} params.objectLayerId - The `_id` of the ObjectLayer document to update.
675
+ * @param {Object} params.ObjectLayer - Mongoose ObjectLayer model.
676
+ * @param {Object} params.ObjectLayerRenderFrames - Mongoose ObjectLayerRenderFrames model.
677
+ * @param {ObjectLayerRenderFramesData} params.objectLayerRenderFramesData - Render frames payload.
678
+ * @param {Object} params.objectLayerData - Object layer payload (must include `data`).
679
+ * @param {CreateDocumentsOptions} [params.updateOptions={}] - Additional options controlling atlas generation and IPFS pinning.
680
+ * @returns {Promise<CreateDocumentsResult>} The persisted documents.
681
+ * @memberof CyberiaObjectLayer
682
+ */
683
+ static async updateObjectLayerDocuments({
684
+ objectLayerId,
685
+ ObjectLayer,
686
+ ObjectLayerRenderFrames,
687
+ objectLayerRenderFramesData,
688
+ objectLayerData,
689
+ updateOptions = {},
690
+ }) {
691
+ const { generateAtlas = true, atlasServiceContext = null } = updateOptions;
692
+
693
+ // 1. Load existing ObjectLayer to get old references
694
+ const existingObjectLayer = await ObjectLayer.findById(objectLayerId);
695
+ if (!existingObjectLayer) {
696
+ throw new Error('ObjectLayer not found for update');
697
+ }
698
+ const oldRenderFramesId = existingObjectLayer.objectLayerRenderFramesId;
699
+
700
+ // 2. Create NEW RenderFrames (avoid mutating old doc mid-update)
701
+ const objectLayerRenderFramesDoc = await ObjectLayerRenderFrames.create(objectLayerRenderFramesData);
702
+ objectLayerData.objectLayerRenderFramesId = objectLayerRenderFramesDoc._id;
703
+
704
+ // 3. Set up render CIDs
705
+ if (!objectLayerData.data.render) objectLayerData.data.render = {};
706
+ objectLayerData.data.render.cid = '';
707
+ objectLayerData.data.render.metadataCid = '';
708
+
709
+ // 4. Stage atlas + IPFS CIDs BEFORE updating the ObjectLayer
710
+ if (generateAtlas && atlasServiceContext) {
711
+ const {
712
+ req,
713
+ res,
714
+ options,
715
+ AtlasSpriteSheetService,
716
+ IpfsClient: ipfsClient,
717
+ createPinRecord,
718
+ } = atlasServiceContext;
719
+
720
+ try {
721
+ const stagingOL = {
722
+ data: objectLayerData.data,
723
+ objectLayerRenderFramesId: objectLayerRenderFramesDoc,
724
+ };
725
+ const result = await AtlasSpriteSheetService.generate(
726
+ { objectLayer: stagingOL, auth: req ? req.auth : undefined },
727
+ res,
728
+ options,
729
+ { skipObjectLayerSave: true },
730
+ );
731
+ objectLayerData.data.render.cid = result.atlasCid;
732
+ objectLayerData.data.render.metadataCid = result.atlasMetadataCid;
733
+ objectLayerData.atlasSpriteSheetId = result.atlasDoc._id;
734
+ } catch (atlasError) {
735
+ logger.error('Failed to generate atlas during update staging:', atlasError);
736
+ }
737
+
738
+ // Compute final SHA-256 (includes render CIDs)
739
+ objectLayerData.sha256 = ObjectLayerEngine.computeSha256(objectLayerData.data);
740
+
741
+ // Pin data JSON to IPFS
742
+ if (ipfsClient) {
743
+ try {
744
+ const itemId = objectLayerData.data.item.id;
745
+ const mfsPath = `/object-layer/${itemId}/${itemId}_data.json`;
746
+ const ipfsResult = await ipfsClient.addJsonToIpfs(objectLayerData.data, `${itemId}_data.json`, mfsPath);
747
+ if (ipfsResult) {
748
+ objectLayerData.cid = ipfsResult.cid;
749
+ if (createPinRecord) {
750
+ await createPinRecord({ cid: ipfsResult.cid, resourceType: 'object-layer-data', mfsPath, options });
751
+ }
752
+ }
753
+ } catch (ipfsError) {
754
+ logger.warn('Failed to pin data JSON to IPFS:', ipfsError.message);
755
+ }
756
+ }
757
+ } else {
758
+ objectLayerData.sha256 = ObjectLayerEngine.computeSha256(objectLayerData.data);
759
+ }
760
+
761
+ // 5. Atomic update - ObjectLayer is fully populated with all CIDs
762
+ let objectLayer;
763
+ try {
764
+ objectLayer = await ObjectLayer.findByIdAndUpdate(objectLayerId, objectLayerData, {
765
+ returnDocument: 'after',
766
+ }).populate('objectLayerRenderFramesId');
767
+ if (!objectLayer) {
768
+ throw new Error('ObjectLayer not found for update');
769
+ }
770
+ logger.info(`ObjectLayer updated atomically with id: ${objectLayerId}`);
771
+ } catch (error) {
772
+ logger.error('Error updating ObjectLayer:', error);
773
+ throw error;
774
+ }
775
+
776
+ // 6. Clean up old RenderFrames
777
+ if (oldRenderFramesId && !oldRenderFramesId.equals(objectLayerRenderFramesDoc._id)) {
778
+ await ObjectLayerRenderFrames.findByIdAndDelete(oldRenderFramesId);
779
+ }
780
+
781
+ return { objectLayer, objectLayerRenderFramesDoc };
782
+ }
783
+
784
+ /**
785
+ * Recomputes the definitive SHA-256, pins the object layer data JSON to IPFS,
786
+ * and persists both fields on the ObjectLayer document.
787
+ *
788
+ * Intended for use after atlas generation has set `data.render.cid`.
789
+ *
790
+ * @static
791
+ * @param {Object} params - Parameters.
792
+ * @param {Object} params.objectLayer - The mongoose ObjectLayer document (must be populated).
793
+ * @param {Object} [params.ipfsClient=null] - The IpfsClient module; when `null`, IPFS pinning is skipped.
794
+ * @param {function} [params.createPinRecord=null] - The `createPinRecord` helper; when `null`, pin records are skipped.
795
+ * @param {Object} [params.options] - Server options (host, path) forwarded to `createPinRecord`.
796
+ * @returns {Promise<Object>} The saved ObjectLayer document.
797
+ * @memberof CyberiaObjectLayer
798
+ */
799
+ static async computeAndSaveFinalSha256({ objectLayer, ipfsClient = null, createPinRecord = null, options }) {
800
+ const finalSha256 = ObjectLayerEngine.computeSha256(objectLayer.data);
801
+
802
+ if (ipfsClient) {
803
+ try {
804
+ const itemId = objectLayer.data.item.id;
805
+ const mfsPath = `/object-layer/${itemId}/${itemId}_data.json`;
806
+ const ipfsResult = await ipfsClient.addJsonToIpfs(objectLayer.data, `${itemId}_data.json`, mfsPath);
807
+ if (ipfsResult) {
808
+ objectLayer.cid = ipfsResult.cid;
809
+ if (createPinRecord) {
810
+ await createPinRecord({ cid: ipfsResult.cid, resourceType: 'object-layer-data', mfsPath, options });
811
+ }
812
+ }
813
+ } catch (ipfsError) {
814
+ logger.warn('Failed to add object layer data to IPFS:', ipfsError.message);
815
+ }
816
+ }
817
+
818
+ objectLayer.sha256 = finalSha256;
819
+ objectLayer.markModified('data');
820
+ await objectLayer.save();
821
+
822
+ return objectLayer;
823
+ }
824
+
825
+ /**
826
+ * Resolve the canonical CID for an Object Layer item from the database.
827
+ *
828
+ * The canonical CID is the IPFS content identifier of the stable-JSON-serialised
829
+ * `objectLayer.data` document (produced by `fast-json-stable-stringify`). This is
830
+ * the CID that MUST be stored on-chain as the metadata CID so that any party can
831
+ * independently reproduce the hash from the same semantic payload.
832
+ *
833
+ * Resolution order:
834
+ * 1. If the ObjectLayer document already has a `.cid` field, use it.
835
+ * 2. Otherwise compute it on-the-fly via `ipfsClient.addJsonToIpfs` (pins the
836
+ * data to IPFS as a side-effect) and persist it back to the document.
837
+ * 3. If IPFS is unreachable, fall back to a local SHA-256 so the caller at
838
+ * least gets a content hash (prefixed with `sha256:` to distinguish it
839
+ * from a real IPFS CID).
840
+ *
841
+ * @static
842
+ * @param {Object} params
843
+ * @param {string} params.itemId – human-readable item identifier.
844
+ * @param {import('mongoose').Model} params.ObjectLayer – Mongoose ObjectLayer model.
845
+ * @param {Object} [params.ipfsClient=null] – The IpfsClient module; when `null`, IPFS pinning is skipped and only SHA-256 fallback is returned.
846
+ * @param {Object} [params.options] – `{ host, path }` forwarded to pin helpers.
847
+ * @returns {Promise<{ cid: string, sha256: string, source: string }>}
848
+ * @memberof CyberiaObjectLayer
849
+ */
850
+ static async resolveCanonicalCid({ itemId, ObjectLayer, ipfsClient = null, options }) {
851
+ const objectLayer = await ObjectLayer.findOne({ 'data.item.id': itemId });
852
+ if (!objectLayer) {
853
+ throw new Error(`ObjectLayer "${itemId}" not found in database`);
854
+ }
855
+
856
+ const sha256 = ObjectLayerEngine.computeSha256(objectLayer.data);
857
+
858
+ // 1. Already have a canonical CID persisted
859
+ if (objectLayer.cid) {
860
+ return { cid: objectLayer.cid, sha256, source: 'db' };
861
+ }
862
+
863
+ // 2. Try to compute and persist via IPFS
864
+ if (ipfsClient) {
865
+ try {
866
+ const ipfsResult = await ipfsClient.addJsonToIpfs(
867
+ objectLayer.data,
868
+ `${itemId}_data.json`,
869
+ `/object-layer/${itemId}/${itemId}_data.json`,
870
+ );
871
+ if (ipfsResult) {
872
+ objectLayer.cid = ipfsResult.cid;
873
+ objectLayer.sha256 = sha256;
874
+ objectLayer.markModified('data');
875
+ await objectLayer.save();
876
+ logger.info(`Canonical CID computed and persisted for "${itemId}": ${ipfsResult.cid}`);
877
+ return { cid: ipfsResult.cid, sha256, source: 'ipfs' };
878
+ }
879
+ } catch (err) {
880
+ logger.warn(`IPFS unreachable while resolving canonical CID for "${itemId}": ${err.message}`);
881
+ }
882
+ }
883
+
884
+ // 3. Fallback – return a sha256:-prefixed content hash
885
+ logger.warn(
886
+ `Using SHA-256 fallback for "${itemId}" (IPFS unavailable). On-chain CID will not resolve via gateway.`,
887
+ );
888
+ return { cid: `sha256:${sha256}`, sha256, source: 'sha256-fallback' };
889
+ }
890
+ }
891
+
892
+ // ──────────────────────────────────────────────────────────────────────────
893
+ // Backward-compatible named exports matching the original destructured imports.
894
+ // ──────────────────────────────────────────────────────────────────────────
895
+
896
+ /**
897
+ * @see {@link ObjectLayerEngine.pngDirectoryIteratorByObjectLayerType}
898
+ * @function pngDirectoryIteratorByObjectLayerType
899
+ * @memberof CyberiaObjectLayer
900
+ */
901
+ export const pngDirectoryIteratorByObjectLayerType = ObjectLayerEngine.pngDirectoryIteratorByObjectLayerType;
902
+
903
+ /**
904
+ * @see {@link ObjectLayerEngine.readPngAsync}
905
+ * @function readPngAsync
906
+ * @memberof CyberiaObjectLayer
907
+ */
908
+ export const readPngAsync = ObjectLayerEngine.readPngAsync;
909
+
910
+ /**
911
+ * @see {@link ObjectLayerEngine.frameFactory}
912
+ * @function frameFactory
913
+ * @memberof CyberiaObjectLayer
914
+ */
915
+ export const frameFactory = ObjectLayerEngine.frameFactory;
916
+
917
+ /**
918
+ * @see {@link ObjectLayerEngine.processAndPushFrame}
919
+ * @function processAndPushFrame
920
+ * @memberof CyberiaObjectLayer
921
+ */
922
+ export const processAndPushFrame = ObjectLayerEngine.processAndPushFrame;
923
+
924
+ /**
925
+ * @see {@link ObjectLayerEngine.buildImgFromTile}
926
+ * @function buildImgFromTile
927
+ * @memberof CyberiaObjectLayer
928
+ */
929
+ export const buildImgFromTile = ObjectLayerEngine.buildImgFromTile;
930
+
931
+ /**
932
+ * @see {@link ObjectLayerEngine.buildObjectLayerDataFromDirectory}
933
+ * @function buildObjectLayerDataFromDirectory
934
+ * @memberof CyberiaObjectLayer
935
+ */
936
+ export const buildObjectLayerDataFromDirectory = ObjectLayerEngine.buildObjectLayerDataFromDirectory;
937
+
938
+ /**
939
+ * @see {@link ObjectLayerEngine.computeSha256}
940
+ * @function computeSha256
941
+ * @memberof CyberiaObjectLayer
942
+ */
943
+ export const computeSha256 = ObjectLayerEngine.computeSha256;
944
+
945
+ /**
946
+ * @see {@link ObjectLayerEngine.createObjectLayerDocuments}
947
+ * @function createObjectLayerDocuments
948
+ * @memberof CyberiaObjectLayer
949
+ */
950
+ export const createObjectLayerDocuments = ObjectLayerEngine.createObjectLayerDocuments;
951
+
952
+ /**
953
+ * @see {@link ObjectLayerEngine.updateObjectLayerDocuments}
954
+ * @function updateObjectLayerDocuments
955
+ * @memberof CyberiaObjectLayer
956
+ */
957
+ export const updateObjectLayerDocuments = ObjectLayerEngine.updateObjectLayerDocuments;
958
+
959
+ /**
960
+ * @see {@link ObjectLayerEngine.computeAndSaveFinalSha256}
961
+ * @function computeAndSaveFinalSha256
962
+ * @memberof CyberiaObjectLayer
963
+ */
964
+ export const computeAndSaveFinalSha256 = ObjectLayerEngine.computeAndSaveFinalSha256;
965
+
966
+ /**
967
+ * @see {@link ObjectLayerEngine.writeStaticFrameAssets}
968
+ * @function writeStaticFrameAssets
969
+ * @memberof CyberiaObjectLayer
970
+ */
971
+ export const writeStaticFrameAssets = ObjectLayerEngine.writeStaticFrameAssets;
972
+
973
+ /**
974
+ * @see {@link ObjectLayerEngine.resolveCanonicalCid}
975
+ * @function resolveCanonicalCid
976
+ * @memberof CyberiaObjectLayer
977
+ */
978
+ export const resolveCanonicalCid = ObjectLayerEngine.resolveCanonicalCid;