cyberia 3.0.3 → 3.2.5

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 (296) hide show
  1. package/{.env.production → .env.example} +20 -4
  2. package/.github/workflows/engine-cyberia.cd.yml +43 -10
  3. package/.github/workflows/engine-cyberia.ci.yml +48 -26
  4. package/.github/workflows/ghpkg.ci.yml +5 -5
  5. package/.github/workflows/gitlab.ci.yml +1 -1
  6. package/.github/workflows/hardhat.ci.yml +82 -0
  7. package/.github/workflows/npmpkg.ci.yml +60 -14
  8. package/.github/workflows/publish.ci.yml +26 -7
  9. package/.github/workflows/publish.cyberia.ci.yml +5 -5
  10. package/.github/workflows/pwa-microservices-template-page.cd.yml +6 -7
  11. package/.github/workflows/pwa-microservices-template-test.ci.yml +4 -4
  12. package/.github/workflows/release.cd.yml +14 -8
  13. package/.vscode/extensions.json +9 -8
  14. package/.vscode/settings.json +3 -2
  15. package/CHANGELOG.md +643 -1
  16. package/CLI-HELP.md +132 -57
  17. package/Dockerfile +4 -2
  18. package/README.md +347 -22
  19. package/WHITE-PAPER.md +1540 -0
  20. package/bin/build.js +21 -12
  21. package/bin/cyberia.js +2640 -106
  22. package/bin/deploy.js +258 -372
  23. package/bin/file.js +5 -1
  24. package/bin/index.js +2640 -106
  25. package/bin/vs.js +3 -3
  26. package/conf.js +169 -105
  27. package/deployment.yaml +236 -20
  28. package/hardhat/.env.example +31 -0
  29. package/hardhat/README.md +531 -0
  30. package/hardhat/WHITE-PAPER.md +1540 -0
  31. package/hardhat/contracts/ObjectLayerToken.sol +391 -0
  32. package/hardhat/deployments/.gitkeep +0 -0
  33. package/hardhat/deployments/hardhat-ObjectLayerToken.json +11 -0
  34. package/hardhat/hardhat.config.js +136 -0
  35. package/hardhat/ignition/modules/ObjectLayerToken.js +21 -0
  36. package/hardhat/networks/besu-object-layer.network.json +138 -0
  37. package/hardhat/package-lock.json +4323 -0
  38. package/hardhat/package.json +36 -0
  39. package/hardhat/scripts/deployObjectLayerToken.js +98 -0
  40. package/hardhat/test/ObjectLayerToken.js +592 -0
  41. package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
  42. package/hardhat/types/ethers-contracts/common.ts +92 -0
  43. package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
  44. package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
  45. package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
  46. package/hardhat/types/ethers-contracts/index.ts +6 -0
  47. package/jsdoc.dd-cyberia.json +68 -0
  48. package/jsdoc.json +65 -49
  49. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +5 -4
  50. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +5 -4
  51. package/manifests/deployment/dd-cyberia-development/deployment.yaml +562 -0
  52. package/manifests/deployment/dd-cyberia-development/proxy.yaml +297 -0
  53. package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +132 -0
  54. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  55. package/manifests/deployment/dd-test-development/deployment.yaml +88 -74
  56. package/manifests/deployment/dd-test-development/proxy.yaml +13 -4
  57. package/manifests/deployment/playwright/deployment.yaml +1 -1
  58. package/manifests/pv-pvc-dd.yaml +1 -1
  59. package/nodemon.json +1 -1
  60. package/package.json +60 -48
  61. package/proxy.yaml +118 -10
  62. package/pv-pvc.yaml +132 -0
  63. package/scripts/k3s-node-setup.sh +1 -1
  64. package/scripts/ports-ls.sh +2 -0
  65. package/scripts/rhel-grpc-setup.sh +56 -0
  66. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +47 -1
  67. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +17 -2
  68. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +5 -0
  69. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +80 -7
  70. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +93 -0
  71. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
  72. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +29 -0
  73. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +51 -0
  74. package/src/api/cyberia-entity/cyberia-entity.controller.js +74 -0
  75. package/src/api/cyberia-entity/cyberia-entity.model.js +24 -0
  76. package/src/api/cyberia-entity/cyberia-entity.router.js +27 -0
  77. package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
  78. package/src/api/cyberia-instance/cyberia-fallback-world.js +368 -0
  79. package/src/api/cyberia-instance/cyberia-instance.controller.js +92 -0
  80. package/src/api/cyberia-instance/cyberia-instance.model.js +84 -0
  81. package/src/api/cyberia-instance/cyberia-instance.router.js +63 -0
  82. package/src/api/cyberia-instance/cyberia-instance.service.js +191 -0
  83. package/src/api/cyberia-instance/cyberia-portal-connector.js +486 -0
  84. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +74 -0
  85. package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +413 -0
  86. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +228 -0
  87. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +27 -0
  88. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +42 -0
  89. package/src/api/cyberia-map/cyberia-map.controller.js +79 -0
  90. package/src/api/cyberia-map/cyberia-map.model.js +30 -0
  91. package/src/api/cyberia-map/cyberia-map.router.js +40 -0
  92. package/src/api/cyberia-map/cyberia-map.service.js +74 -0
  93. package/src/api/document/document.service.js +1 -1
  94. package/src/api/file/file.controller.js +3 -1
  95. package/src/api/file/file.ref.json +18 -0
  96. package/src/api/file/file.service.js +28 -5
  97. package/src/api/ipfs/ipfs.controller.js +4 -25
  98. package/src/api/ipfs/ipfs.model.js +43 -34
  99. package/src/api/ipfs/ipfs.router.js +8 -13
  100. package/src/api/ipfs/ipfs.service.js +56 -104
  101. package/src/api/object-layer/README.md +347 -22
  102. package/src/api/object-layer/object-layer.controller.js +6 -2
  103. package/src/api/object-layer/object-layer.model.js +12 -8
  104. package/src/api/object-layer/object-layer.router.js +698 -42
  105. package/src/api/object-layer/object-layer.service.js +119 -37
  106. package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +1 -2
  107. package/src/api/user/user.router.js +10 -5
  108. package/src/api/user/user.service.js +15 -14
  109. package/src/cli/baremetal.js +6 -10
  110. package/src/cli/cloud-init.js +0 -3
  111. package/src/cli/cluster.js +7 -7
  112. package/src/cli/db.js +723 -857
  113. package/src/cli/deploy.js +215 -105
  114. package/src/cli/env.js +34 -5
  115. package/src/cli/fs.js +5 -4
  116. package/src/cli/image.js +0 -3
  117. package/src/cli/index.js +83 -15
  118. package/src/cli/kubectl.js +211 -0
  119. package/src/cli/monitor.js +5 -6
  120. package/src/cli/release.js +284 -0
  121. package/src/cli/repository.js +708 -62
  122. package/src/cli/run.js +371 -151
  123. package/src/cli/secrets.js +73 -2
  124. package/src/cli/ssh.js +1 -1
  125. package/src/cli/test.js +3 -3
  126. package/src/client/Cryptokoyn.index.js +3 -4
  127. package/src/client/CyberiaPortal.index.js +3 -4
  128. package/src/client/Default.index.js +3 -4
  129. package/src/client/Itemledger.index.js +4 -963
  130. package/src/client/Underpost.index.js +3 -4
  131. package/src/client/components/core/AgGrid.js +20 -5
  132. package/src/client/components/core/Alert.js +2 -2
  133. package/src/client/components/core/AppStore.js +69 -0
  134. package/src/client/components/core/CalendarCore.js +2 -2
  135. package/src/client/components/core/Content.js +22 -3
  136. package/src/client/components/core/Docs.js +30 -6
  137. package/src/client/components/core/DropDown.js +137 -17
  138. package/src/client/components/core/FileExplorer.js +71 -4
  139. package/src/client/components/core/Input.js +1 -1
  140. package/src/client/components/core/Keyboard.js +2 -2
  141. package/src/client/components/core/LogIn.js +2 -2
  142. package/src/client/components/core/LogOut.js +2 -2
  143. package/src/client/components/core/Modal.js +20 -7
  144. package/src/client/components/core/Panel.js +0 -1
  145. package/src/client/components/core/PanelForm.js +19 -19
  146. package/src/client/components/core/RichText.js +1 -2
  147. package/src/client/components/core/SocketIo.js +82 -29
  148. package/src/client/components/core/SocketIoHandler.js +75 -0
  149. package/src/client/components/core/Stream.js +143 -95
  150. package/src/client/components/core/Webhook.js +40 -7
  151. package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
  152. package/src/client/components/cryptokoyn/LogInCryptokoyn.js +3 -3
  153. package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +2 -2
  154. package/src/client/components/cryptokoyn/MenuCryptokoyn.js +3 -3
  155. package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +3 -51
  156. package/src/client/components/cyberia/InstanceEngineCyberia.js +700 -0
  157. package/src/client/components/cyberia/MapEngineCyberia.js +1359 -2
  158. package/src/client/components/cyberia/ObjectLayerEngineModal.js +17 -6
  159. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +92 -54
  160. package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
  161. package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +217 -30
  162. package/src/client/components/cyberia-portal/CssCyberiaPortal.js +44 -2
  163. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +3 -4
  164. package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +2 -2
  165. package/src/client/components/cyberia-portal/MenuCyberiaPortal.js +104 -9
  166. package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +5 -0
  167. package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +3 -49
  168. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
  169. package/src/client/components/default/AppStoreDefault.js +5 -0
  170. package/src/client/components/default/LogInDefault.js +3 -3
  171. package/src/client/components/default/LogOutDefault.js +2 -2
  172. package/src/client/components/default/MenuDefault.js +5 -5
  173. package/src/client/components/default/SocketIoDefault.js +3 -51
  174. package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
  175. package/src/client/components/itemledger/LogInItemledger.js +3 -3
  176. package/src/client/components/itemledger/LogOutItemledger.js +2 -2
  177. package/src/client/components/itemledger/MenuItemledger.js +3 -3
  178. package/src/client/components/itemledger/SocketIoItemledger.js +3 -51
  179. package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
  180. package/src/client/components/underpost/CssUnderpost.js +59 -0
  181. package/src/client/components/underpost/LogInUnderpost.js +6 -3
  182. package/src/client/components/underpost/LogOutUnderpost.js +4 -2
  183. package/src/client/components/underpost/MenuUnderpost.js +104 -18
  184. package/src/client/components/underpost/RoutesUnderpost.js +2 -0
  185. package/src/client/components/underpost/SocketIoUnderpost.js +3 -51
  186. package/src/client/public/cryptokoyn/assets/logo/base-icon.png +0 -0
  187. package/src/client/public/cryptokoyn/browserconfig.xml +12 -0
  188. package/src/client/public/cryptokoyn/microdata.json +85 -0
  189. package/src/client/public/cryptokoyn/site.webmanifest +57 -0
  190. package/src/client/public/cryptokoyn/sitemap +3 -3
  191. package/src/client/public/default/sitemap +3 -3
  192. package/src/client/public/itemledger/browserconfig.xml +2 -2
  193. package/src/client/public/itemledger/manifest.webmanifest +4 -4
  194. package/src/client/public/itemledger/microdata.json +71 -0
  195. package/src/client/public/itemledger/sitemap +3 -3
  196. package/src/client/public/itemledger/yandex-browser-manifest.json +2 -2
  197. package/src/client/public/test/sitemap +3 -3
  198. package/src/client/services/core/core.service.js +20 -8
  199. package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +105 -0
  200. package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
  201. package/src/client/services/cyberia-entity/cyberia-entity.service.js +105 -0
  202. package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
  203. package/src/client/services/cyberia-instance/cyberia-instance.service.js +122 -0
  204. package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +105 -0
  205. package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
  206. package/src/client/services/cyberia-map/cyberia-map.service.js +126 -0
  207. package/src/client/services/instance/instance.management.js +2 -2
  208. package/src/client/services/ipfs/ipfs.service.js +3 -23
  209. package/src/client/services/object-layer/object-layer.management.js +3 -3
  210. package/src/client/services/object-layer/object-layer.service.js +21 -0
  211. package/src/client/services/user/user.management.js +2 -2
  212. package/src/client/ssr/body/404.js +15 -11
  213. package/src/client/ssr/body/500.js +15 -11
  214. package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
  215. package/src/client/ssr/head/PwaItemledger.js +60 -0
  216. package/src/client/ssr/offline/NoNetworkConnection.js +11 -10
  217. package/src/client/ssr/pages/CyberiaServerMetrics.js +1 -1
  218. package/src/client/ssr/pages/Test.js +11 -10
  219. package/src/client.build.js +0 -3
  220. package/src/client.dev.js +0 -3
  221. package/src/db/DataBaseProvider.js +17 -2
  222. package/src/db/mariadb/MariaDB.js +14 -9
  223. package/src/db/mongo/MongooseDB.js +17 -1
  224. package/src/grpc/cyberia/OFF_CHAIN_ECONOMY.md +305 -0
  225. package/src/grpc/cyberia/README.md +326 -0
  226. package/src/grpc/cyberia/grpc-server.js +530 -0
  227. package/src/index.js +24 -1
  228. package/src/proxy.js +0 -3
  229. package/src/runtime/express/Dockerfile +4 -0
  230. package/src/runtime/express/Express.js +33 -10
  231. package/src/runtime/lampp/Dockerfile +13 -2
  232. package/src/runtime/lampp/Lampp.js +33 -17
  233. package/src/runtime/wp/Dockerfile +68 -0
  234. package/src/runtime/wp/Wp.js +639 -0
  235. package/src/server/auth.js +36 -15
  236. package/src/server/backup.js +39 -12
  237. package/src/server/besu-genesis-generator.js +1630 -0
  238. package/src/server/client-build-docs.js +133 -17
  239. package/src/server/client-build-live.js +9 -18
  240. package/src/server/client-build.js +229 -101
  241. package/src/server/client-dev-server.js +14 -13
  242. package/src/server/client-formatted.js +109 -57
  243. package/src/server/conf.js +391 -164
  244. package/src/server/cron.js +27 -24
  245. package/src/server/dns.js +29 -12
  246. package/src/server/downloader.js +0 -2
  247. package/src/server/ipfs-client.js +24 -1
  248. package/src/server/logger.js +27 -9
  249. package/src/server/object-layer.js +217 -103
  250. package/src/server/peer.js +8 -2
  251. package/src/server/process.js +1 -50
  252. package/src/server/proxy.js +4 -8
  253. package/src/server/runtime.js +30 -9
  254. package/src/server/semantic-layer-generator-floor.js +359 -0
  255. package/src/server/semantic-layer-generator-skin.js +1294 -0
  256. package/src/server/semantic-layer-generator.js +116 -555
  257. package/src/server/ssr.js +0 -3
  258. package/src/server/start.js +19 -12
  259. package/src/server/tls.js +0 -2
  260. package/src/server.js +0 -4
  261. package/src/ws/IoInterface.js +1 -10
  262. package/src/ws/IoServer.js +14 -33
  263. package/src/ws/core/channels/core.ws.chat.js +65 -20
  264. package/src/ws/core/channels/core.ws.mailer.js +113 -32
  265. package/src/ws/core/channels/core.ws.stream.js +90 -31
  266. package/src/ws/core/core.ws.connection.js +12 -33
  267. package/src/ws/core/core.ws.emit.js +10 -26
  268. package/src/ws/core/core.ws.server.js +25 -58
  269. package/src/ws/default/channels/default.ws.main.js +53 -12
  270. package/src/ws/default/default.ws.connection.js +26 -13
  271. package/src/ws/default/default.ws.server.js +30 -12
  272. package/.env.development +0 -43
  273. package/.env.test +0 -43
  274. package/hardhat/contracts/CryptoKoyn.sol +0 -59
  275. package/hardhat/contracts/ItemLedger.sol +0 -73
  276. package/hardhat/contracts/Lock.sol +0 -34
  277. package/hardhat/hardhat.config.cjs +0 -45
  278. package/hardhat/ignition/modules/Lock.js +0 -18
  279. package/hardhat/networks/cryptokoyn-itemledger.network.json +0 -29
  280. package/hardhat/scripts/deployCryptokoyn.cjs +0 -25
  281. package/hardhat/scripts/deployItemledger.cjs +0 -25
  282. package/hardhat/test/Lock.js +0 -126
  283. package/hardhat/white-paper.md +0 -581
  284. package/src/client/components/cryptokoyn/CommonCryptokoyn.js +0 -29
  285. package/src/client/components/cryptokoyn/ElementsCryptokoyn.js +0 -38
  286. package/src/client/components/cyberia-portal/ElementsCyberiaPortal.js +0 -38
  287. package/src/client/components/default/ElementsDefault.js +0 -38
  288. package/src/client/components/itemledger/CommonItemledger.js +0 -29
  289. package/src/client/components/itemledger/ElementsItemledger.js +0 -38
  290. package/src/client/components/underpost/CommonUnderpost.js +0 -29
  291. package/src/client/components/underpost/ElementsUnderpost.js +0 -38
  292. package/src/ws/core/management/core.ws.chat.js +0 -8
  293. package/src/ws/core/management/core.ws.mailer.js +0 -16
  294. package/src/ws/core/management/core.ws.stream.js +0 -8
  295. package/src/ws/default/management/default.ws.main.js +0 -8
  296. package/white-paper.md +0 -581
@@ -4,6 +4,26 @@ import { AtlasSpriteSheetService } from './atlas-sprite-sheet.service.js';
4
4
  const logger = loggerFactory(import.meta);
5
5
 
6
6
  const AtlasSpriteSheetController = {
7
+ blob: async (req, res, options) => {
8
+ try {
9
+ if (req && req.headers && req.headers.origin) {
10
+ res.set('Access-Control-Allow-Origin', req.headers.origin);
11
+ } else res.setHeader('Access-Control-Allow-Origin', '*');
12
+ res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
13
+
14
+ const { buffer, mimetype, name } = await AtlasSpriteSheetService.blob(req, res, options);
15
+ res.set('Content-Type', mimetype);
16
+ res.set('Content-Length', buffer.length);
17
+ res.set('Content-Disposition', `inline; filename="${name}"`);
18
+ return res.status(200).end(buffer);
19
+ } catch (error) {
20
+ logger.error('AtlasSpriteSheetController.blob error:', error);
21
+ return res.status(404).json({
22
+ status: 'error',
23
+ message: error.message,
24
+ });
25
+ }
26
+ },
7
27
  generate: async (req, res, options) => {
8
28
  try {
9
29
  const result = await AtlasSpriteSheetService.generate(req, res, options);
@@ -51,7 +71,9 @@ const AtlasSpriteSheetController = {
51
71
  },
52
72
  get: async (req, res, options) => {
53
73
  try {
54
- res.setHeader('Access-Control-Allow-Origin', '*');
74
+ if (req && req.headers && req.headers.origin) {
75
+ res.set('Access-Control-Allow-Origin', req.headers.origin);
76
+ } else res.setHeader('Access-Control-Allow-Origin', '*');
55
77
  res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
56
78
  const { page, limit } = req.query;
57
79
  const result = await AtlasSpriteSheetService.get(
@@ -101,6 +123,30 @@ const AtlasSpriteSheetController = {
101
123
  });
102
124
  }
103
125
  },
126
+ getMetadata: async (req, res, options) => {
127
+ try {
128
+ if (req && req.headers && req.headers.origin) {
129
+ res.set('Access-Control-Allow-Origin', req.headers.origin);
130
+ } else res.setHeader('Access-Control-Allow-Origin', '*');
131
+ res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
132
+ const { page, limit } = req.query;
133
+ const result = await AtlasSpriteSheetService.getMetadata(
134
+ { ...req, query: { ...req.query, page: parseInt(page), limit: parseInt(limit) } },
135
+ res,
136
+ options,
137
+ );
138
+ return res.status(200).json({
139
+ status: 'success',
140
+ data: result,
141
+ });
142
+ } catch (error) {
143
+ logger.error(error, error.stack);
144
+ return res.status(404).json({
145
+ status: 'error',
146
+ message: error.message,
147
+ });
148
+ }
149
+ },
104
150
  };
105
151
 
106
152
  export { AtlasSpriteSheetController };
@@ -118,11 +118,10 @@ AtlasSpriteSheetSchema.index({ 'metadata.itemKey': 1 }, { unique: true });
118
118
  AtlasSpriteSheetSchema.index({ fileId: 1 });
119
119
 
120
120
  // Pre-save validation
121
- AtlasSpriteSheetSchema.pre('save', function (next) {
121
+ AtlasSpriteSheetSchema.pre('save', function () {
122
122
  if (!this.fileId || !this.metadata) {
123
123
  throw new Error('AtlasSpriteSheet missing required fields: fileId or metadata');
124
124
  }
125
- next();
126
125
  });
127
126
 
128
127
  const AtlasSpriteSheetModel = model('AtlasSpriteSheet', AtlasSpriteSheetSchema);
@@ -141,6 +140,22 @@ const AtlasSpriteSheetDto = {
141
140
  updatedAt: 1,
142
141
  };
143
142
  },
143
+ // Returns all fields the client needs per itemKey:
144
+ // layout dims + frames for rendering, no fileId.
145
+ // Client flow: GET /metadata/:itemKey → cache → GET /blob/:itemKey → cache PNG.
146
+ getMetadataOnly: () => {
147
+ return {
148
+ _id: 1,
149
+ cid: 1,
150
+ 'metadata.itemKey': 1,
151
+ 'metadata.atlasWidth': 1,
152
+ 'metadata.atlasHeight': 1,
153
+ 'metadata.cellPixelDim': 1,
154
+ 'metadata.frames': 1,
155
+ createdAt: 1,
156
+ updatedAt: 1,
157
+ };
158
+ },
144
159
  },
145
160
  };
146
161
 
@@ -19,6 +19,11 @@ const AtlasSpriteSheetRouter = (options) => {
19
19
  );
20
20
  router.post(`/:id`, authMiddleware, async (req, res) => await AtlasSpriteSheetController.post(req, res, options));
21
21
  router.post(`/`, authMiddleware, async (req, res) => await AtlasSpriteSheetController.post(req, res, options));
22
+ router.get(`/blob/:itemKey`, async (req, res) => await AtlasSpriteSheetController.blob(req, res, options));
23
+ // Metadata endpoints: returns itemKey, atlasWidth, atlasHeight, cellPixelDim, frames (no fileId).
24
+ // Client fetches /metadata/:itemKey once, caches it, then fetches /blob/:itemKey for the PNG.
25
+ router.get(`/metadata/:itemKey`, async (req, res) => await AtlasSpriteSheetController.getMetadata(req, res, options));
26
+ router.get(`/metadata`, async (req, res) => await AtlasSpriteSheetController.getMetadata(req, res, options));
22
27
  router.get(
23
28
  `/:id`,
24
29
  // authMiddleware,
@@ -10,7 +10,23 @@ import { createPinRecord, removePinRecordsAndUnpin } from '../ipfs/ipfs.service.
10
10
  const logger = loggerFactory(import.meta);
11
11
 
12
12
  const AtlasSpriteSheetService = {
13
- generate: async (req, res, options) => {
13
+ blob: async (req, res, options) => {
14
+ /** @type {import('./atlas-sprite-sheet.model.js').AtlasSpriteSheetModel} */
15
+ const AtlasSpriteSheet =
16
+ DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.AtlasSpriteSheet;
17
+ /** @type {import('../file/file.model.js').FileModel} */
18
+ const File = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.File;
19
+
20
+ const itemKey = req.params.itemKey;
21
+ const atlasDoc = await AtlasSpriteSheet.findOne({ 'metadata.itemKey': itemKey }).lean();
22
+ if (!atlasDoc) throw new Error(`Atlas not found for itemKey: ${itemKey}`);
23
+
24
+ const fileDoc = await File.findById(atlasDoc.fileId);
25
+ if (!fileDoc || !fileDoc.data) throw new Error(`File not found for atlas itemKey: ${itemKey}`);
26
+
27
+ return { buffer: Buffer.from(fileDoc.data), mimetype: fileDoc.mimetype || 'image/png', name: fileDoc.name };
28
+ },
29
+ generate: async (req, res, options, generateOptions = {}) => {
14
30
  /** @type {import('../object-layer/object-layer.model.js').ObjectLayerModel} */
15
31
  const ObjectLayer = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayer;
16
32
  /** @type {import('../file/file.model.js').FileModel} */
@@ -53,9 +69,6 @@ const AtlasSpriteSheetService = {
53
69
  );
54
70
  if (ipfsResult) {
55
71
  atlasCid = ipfsResult.cid;
56
- if (userId) {
57
- await createPinRecord({ cid: atlasCid, userId, options });
58
- }
59
72
  logger.info(`Atlas sprite sheet pinned to IPFS – CID: ${atlasCid}`);
60
73
  }
61
74
  } catch (ipfsError) {
@@ -71,9 +84,6 @@ const AtlasSpriteSheetService = {
71
84
  );
72
85
  if (metadataIpfsResult) {
73
86
  atlasMetadataCid = metadataIpfsResult.cid;
74
- if (userId) {
75
- await createPinRecord({ cid: atlasMetadataCid, userId, options });
76
- }
77
87
  logger.info(`Atlas metadata pinned to IPFS – CID: ${atlasMetadataCid}`);
78
88
  }
79
89
  } catch (ipfsError) {
@@ -99,6 +109,39 @@ const AtlasSpriteSheetService = {
99
109
  }).save();
100
110
  }
101
111
 
112
+ // Register CIDs in the IPFS registry now that atlasDoc._id is known.
113
+ if (atlasCid) {
114
+ try {
115
+ await createPinRecord({
116
+ cid: atlasCid,
117
+ resourceType: 'atlas-sprite-sheet',
118
+ mfsPath: `/object-layer/${itemKey}/${itemKey}_atlas_sprite_sheet.png`,
119
+ options,
120
+ });
121
+ } catch (e) {
122
+ logger.warn('IPFS registry update failed (atlas PNG):', e.message);
123
+ }
124
+ }
125
+ if (atlasMetadataCid) {
126
+ try {
127
+ await createPinRecord({
128
+ cid: atlasMetadataCid,
129
+ resourceType: 'atlas-metadata',
130
+ mfsPath: `/object-layer/${itemKey}/${itemKey}_atlas_sprite_sheet_metadata.json`,
131
+ options,
132
+ });
133
+ } catch (e) {
134
+ logger.warn('IPFS registry update failed (atlas metadata):', e.message);
135
+ }
136
+ }
137
+
138
+ // When skipObjectLayerSave is set, return CIDs without mutating the OL document.
139
+ // This enables cut-over consistency: callers stage CIDs in memory and write the
140
+ // ObjectLayer atomically only after all CIDs are computed.
141
+ if (generateOptions.skipObjectLayerSave) {
142
+ return { atlasDoc, atlasCid, atlasMetadataCid };
143
+ }
144
+
102
145
  objectLayer.atlasSpriteSheetId = atlasDoc._id;
103
146
  if (!objectLayer.data.render) objectLayer.data.render = {};
104
147
  objectLayer.data.render.cid = atlasCid;
@@ -198,6 +241,36 @@ const AtlasSpriteSheetService = {
198
241
  const totalPages = Math.ceil(total / limit);
199
242
  return { data, total, page, totalPages };
200
243
  },
244
+ // Returns atlas metadata (layout + frames) for the client.
245
+ // Client fetches this once per itemKey, caches it, then fetches the PNG blob.
246
+ getMetadata: async (req, res, options) => {
247
+ /** @type {import('./atlas-sprite-sheet.model.js').AtlasSpriteSheetModel} */
248
+ const AtlasSpriteSheet =
249
+ DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.AtlasSpriteSheet;
250
+
251
+ if (req.params.itemKey) {
252
+ const doc = await AtlasSpriteSheet.findOne({ 'metadata.itemKey': req.params.itemKey })
253
+ .select(AtlasSpriteSheetDto.select.getMetadataOnly())
254
+ .lean();
255
+ if (!doc) throw new Error(`Atlas not found for itemKey: ${req.params.itemKey}`);
256
+ return doc;
257
+ }
258
+
259
+ const { query, sort, skip, limit, page } = DataQuery.parse(req.query);
260
+
261
+ const [data, total] = await Promise.all([
262
+ AtlasSpriteSheet.find(query)
263
+ .select(AtlasSpriteSheetDto.select.getMetadataOnly())
264
+ .sort(sort)
265
+ .limit(limit)
266
+ .skip(skip)
267
+ .lean(),
268
+ AtlasSpriteSheet.countDocuments(query),
269
+ ]);
270
+
271
+ const totalPages = Math.ceil(total / limit);
272
+ return { data, total, page, totalPages };
273
+ },
201
274
  put: async (req, res, options) => {
202
275
  /** @type {import('./atlas-sprite-sheet.model.js').AtlasSpriteSheetModel} */
203
276
  const AtlasSpriteSheet =
@@ -0,0 +1,93 @@
1
+ import { loggerFactory } from '../../server/logger.js';
2
+ import { CyberiaDialogueService } from './cyberia-dialogue.service.js';
3
+
4
+ const logger = loggerFactory(import.meta);
5
+
6
+ const CyberiaDialogueController = {
7
+ post: async (req, res, options) => {
8
+ try {
9
+ const result = await CyberiaDialogueService.post(req, res, options);
10
+ return res.status(200).json({
11
+ status: 'success',
12
+ data: result,
13
+ });
14
+ } catch (error) {
15
+ logger.error(error, error.stack);
16
+ return res.status(400).json({
17
+ status: 'error',
18
+ message: error.message,
19
+ });
20
+ }
21
+ },
22
+ get: async (req, res, options) => {
23
+ try {
24
+ const { page, limit } = req.query;
25
+ const result = await CyberiaDialogueService.get(
26
+ { ...req, query: { ...req.query, page: parseInt(page), limit: parseInt(limit) } },
27
+ res,
28
+ options,
29
+ );
30
+ return res.status(200).json({
31
+ status: 'success',
32
+ data: result,
33
+ });
34
+ } catch (error) {
35
+ logger.error(error, error.stack);
36
+ return res.status(400).json({
37
+ status: 'error',
38
+ message: error.message,
39
+ });
40
+ }
41
+ },
42
+ put: async (req, res, options) => {
43
+ try {
44
+ const result = await CyberiaDialogueService.put(req, res, options);
45
+ return res.status(200).json({
46
+ status: 'success',
47
+ data: result,
48
+ });
49
+ } catch (error) {
50
+ logger.error(error, error.stack);
51
+ return res.status(400).json({
52
+ status: 'error',
53
+ message: error.message,
54
+ });
55
+ }
56
+ },
57
+ delete: async (req, res, options) => {
58
+ try {
59
+ const result = await CyberiaDialogueService.delete(req, res, options);
60
+ return res.status(200).json({
61
+ status: 'success',
62
+ data: result,
63
+ });
64
+ } catch (error) {
65
+ logger.error(error, error.stack);
66
+ return res.status(400).json({
67
+ status: 'error',
68
+ message: error.message,
69
+ });
70
+ }
71
+ },
72
+ getByItemId: async (req, res, options) => {
73
+ try {
74
+ if (req && req.headers && req.headers.origin) {
75
+ res.set('Access-Control-Allow-Origin', req.headers.origin);
76
+ } else res.setHeader('Access-Control-Allow-Origin', '*');
77
+ res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
78
+ const result = await CyberiaDialogueService.getByItemId(req, res, options);
79
+ return res.status(200).json({
80
+ status: 'success',
81
+ data: result,
82
+ });
83
+ } catch (error) {
84
+ logger.error(error, error.stack);
85
+ return res.status(404).json({
86
+ status: 'error',
87
+ message: error.message,
88
+ });
89
+ }
90
+ },
91
+ };
92
+
93
+ export { CyberiaDialogueController };
@@ -0,0 +1,36 @@
1
+ import { Schema, model, Types } from 'mongoose';
2
+
3
+ // https://mongoosejs.com/docs/2.7.x/docs/schematypes.html
4
+
5
+ /**
6
+ * CyberiaDialogue — each document is a single dialogue record tied to an
7
+ * item ID from DefaultCyberiaItems. One item may have many dialogue records
8
+ * (ordered by `order`). The client displays them sequentially when the
9
+ * player interacts with an entity whose active item layers match `itemId`.
10
+ *
11
+ * itemId – references an entry in DefaultCyberiaItems (e.g. "lain", "eiri")
12
+ * order – zero-based index governing the display sequence
13
+ * speaker – display name shown above the dialogue line
14
+ * text – the dialogue line itself
15
+ * mood – optional emotion hint (neutral / angry / sad / happy / …)
16
+ */
17
+ const CyberiaDialogueSchema = new Schema(
18
+ {
19
+ itemId: { type: String, required: true, index: true },
20
+ order: { type: Number, default: 0 },
21
+ speaker: { type: String, default: '' },
22
+ text: { type: String, required: true },
23
+ mood: { type: String, default: 'neutral' },
24
+ },
25
+ {
26
+ timestamps: true,
27
+ },
28
+ );
29
+
30
+ CyberiaDialogueSchema.index({ itemId: 1, order: 1 });
31
+
32
+ const CyberiaDialogueModel = model('CyberiaDialogue', CyberiaDialogueSchema);
33
+
34
+ const ProviderSchema = CyberiaDialogueSchema;
35
+
36
+ export { CyberiaDialogueSchema, CyberiaDialogueModel, ProviderSchema };
@@ -0,0 +1,29 @@
1
+ import { loggerFactory } from '../../server/logger.js';
2
+ import { CyberiaDialogueController } from './cyberia-dialogue.controller.js';
3
+ import express from 'express';
4
+
5
+ const logger = loggerFactory(import.meta);
6
+
7
+ const CyberiaDialogueRouter = (options) => {
8
+ const router = express.Router();
9
+ const authMiddleware = options.authMiddleware;
10
+ router.post(`/:id`, async (req, res) => await CyberiaDialogueController.post(req, res, options));
11
+ router.post(`/`, async (req, res) => await CyberiaDialogueController.post(req, res, options));
12
+ // Direct lookup by itemId — C client fetches dialogue by item key (same pattern as atlas /metadata/:itemKey)
13
+ router.get(`/item/:itemId`, async (req, res) => await CyberiaDialogueController.getByItemId(req, res, options));
14
+ router.get(
15
+ `/:id`,
16
+ // authMiddleware,
17
+ async (req, res) => await CyberiaDialogueController.get(req, res, options),
18
+ );
19
+ router.get(`/`, async (req, res) => await CyberiaDialogueController.get(req, res, options));
20
+ router.put(`/:id`, async (req, res) => await CyberiaDialogueController.put(req, res, options));
21
+ router.put(`/`, async (req, res) => await CyberiaDialogueController.put(req, res, options));
22
+ router.delete(`/:id`, async (req, res) => await CyberiaDialogueController.delete(req, res, options));
23
+ router.delete(`/`, async (req, res) => await CyberiaDialogueController.delete(req, res, options));
24
+ return router;
25
+ };
26
+
27
+ const ApiRouter = CyberiaDialogueRouter;
28
+
29
+ export { ApiRouter, CyberiaDialogueRouter };
@@ -0,0 +1,51 @@
1
+ import { DataBaseProvider } from '../../db/DataBaseProvider.js';
2
+ import { loggerFactory } from '../../server/logger.js';
3
+ import { DataQuery } from '../../server/data-query.js';
4
+
5
+ const logger = loggerFactory(import.meta);
6
+
7
+ const CyberiaDialogueService = {
8
+ post: async (req, res, options) => {
9
+ /** @type {import('./cyberia-dialogue.model.js').CyberiaDialogueModel} */
10
+ const CyberiaDialogue = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaDialogue;
11
+ return await new CyberiaDialogue(req.body).save();
12
+ },
13
+ get: async (req, res, options) => {
14
+ /** @type {import('./cyberia-dialogue.model.js').CyberiaDialogueModel} */
15
+ const CyberiaDialogue = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaDialogue;
16
+ if (req.params.id) return await CyberiaDialogue.findById(req.params.id);
17
+
18
+ // Parse query parameters using DataQuery helper
19
+ const { query, sort, skip, limit, page } = DataQuery.parse(req.query);
20
+
21
+ const [data, total] = await Promise.all([
22
+ CyberiaDialogue.find(query).sort(sort).limit(limit).skip(skip),
23
+ CyberiaDialogue.countDocuments(query),
24
+ ]);
25
+
26
+ const totalPages = Math.ceil(total / limit);
27
+ return { data, total, page, totalPages };
28
+ },
29
+ put: async (req, res, options) => {
30
+ /** @type {import('./cyberia-dialogue.model.js').CyberiaDialogueModel} */
31
+ const CyberiaDialogue = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaDialogue;
32
+ return await CyberiaDialogue.findByIdAndUpdate(req.params.id, req.body);
33
+ },
34
+ delete: async (req, res, options) => {
35
+ /** @type {import('./cyberia-dialogue.model.js').CyberiaDialogueModel} */
36
+ const CyberiaDialogue = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaDialogue;
37
+ if (req.params.id) return await CyberiaDialogue.findByIdAndDelete(req.params.id);
38
+ else return await CyberiaDialogue.deleteMany();
39
+ },
40
+ getByItemId: async (req, res, options) => {
41
+ /** @type {import('./cyberia-dialogue.model.js').CyberiaDialogueModel} */
42
+ const CyberiaDialogue = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaDialogue;
43
+ const { itemId } = req.params;
44
+ if (!itemId) throw new Error('itemId parameter is required');
45
+ const data = await CyberiaDialogue.find({ itemId }).sort({ order: 1 }).lean();
46
+ if (!data.length) throw new Error(`No dialogue found for itemId: ${itemId}`);
47
+ return data;
48
+ },
49
+ };
50
+
51
+ export { CyberiaDialogueService };
@@ -0,0 +1,74 @@
1
+ import { loggerFactory } from '../../server/logger.js';
2
+ import { CyberiaEntityService } from './cyberia-entity.service.js';
3
+
4
+ const logger = loggerFactory(import.meta);
5
+
6
+ const CyberiaEntityController = {
7
+ post: async (req, res, options) => {
8
+ try {
9
+ const result = await CyberiaEntityService.post(req, res, options);
10
+ return res.status(200).json({
11
+ status: 'success',
12
+ data: result,
13
+ });
14
+ } catch (error) {
15
+ logger.error(error, error.stack);
16
+ return res.status(400).json({
17
+ status: 'error',
18
+ message: error.message,
19
+ });
20
+ }
21
+ },
22
+ get: async (req, res, options) => {
23
+ try {
24
+ const { page, limit } = req.query;
25
+ const result = await CyberiaEntityService.get(
26
+ { ...req, query: { ...req.query, page: parseInt(page), limit: parseInt(limit) } },
27
+ res,
28
+ options,
29
+ );
30
+ return res.status(200).json({
31
+ status: 'success',
32
+ data: result,
33
+ });
34
+ } catch (error) {
35
+ logger.error(error, error.stack);
36
+ return res.status(400).json({
37
+ status: 'error',
38
+ message: error.message,
39
+ });
40
+ }
41
+ },
42
+ put: async (req, res, options) => {
43
+ try {
44
+ const result = await CyberiaEntityService.put(req, res, options);
45
+ return res.status(200).json({
46
+ status: 'success',
47
+ data: result,
48
+ });
49
+ } catch (error) {
50
+ logger.error(error, error.stack);
51
+ return res.status(400).json({
52
+ status: 'error',
53
+ message: error.message,
54
+ });
55
+ }
56
+ },
57
+ delete: async (req, res, options) => {
58
+ try {
59
+ const result = await CyberiaEntityService.delete(req, res, options);
60
+ return res.status(200).json({
61
+ status: 'success',
62
+ data: result,
63
+ });
64
+ } catch (error) {
65
+ logger.error(error, error.stack);
66
+ return res.status(400).json({
67
+ status: 'error',
68
+ message: error.message,
69
+ });
70
+ }
71
+ },
72
+ };
73
+
74
+ export { CyberiaEntityController };
@@ -0,0 +1,24 @@
1
+ import { Schema, model, Types } from 'mongoose';
2
+
3
+ // https://mongoosejs.com/docs/2.7.x/docs/schematypes.html
4
+
5
+ const CyberiaEntitySchema = new Schema({
6
+ entityType: { type: String, default: 'floor' },
7
+ initCellX: { type: Number, default: 0 },
8
+ initCellY: { type: Number, default: 0 },
9
+ dimX: { type: Number, default: 1 },
10
+ dimY: { type: Number, default: 1 },
11
+ color: { type: String, default: 'rgba(255, 0, 0, 1)' },
12
+ objectLayerItemIds: { type: [String], default: [] },
13
+ // Bot-specific fields (ignored for non-bot entities)
14
+ spawnRadius: { type: Number, default: 0 },
15
+ aggroRange: { type: Number, default: 0 },
16
+ maxLife: { type: Number, default: 0 },
17
+ lifeRegen: { type: Number, default: 0 },
18
+ });
19
+
20
+ const CyberiaEntityModel = model('CyberiaEntity', CyberiaEntitySchema);
21
+
22
+ const ProviderSchema = CyberiaEntitySchema;
23
+
24
+ export { CyberiaEntitySchema, CyberiaEntityModel, ProviderSchema };
@@ -0,0 +1,27 @@
1
+ import { loggerFactory } from '../../server/logger.js';
2
+ import { CyberiaEntityController } from './cyberia-entity.controller.js';
3
+ import express from 'express';
4
+
5
+ const logger = loggerFactory(import.meta);
6
+
7
+ const CyberiaEntityRouter = (options) => {
8
+ const router = express.Router();
9
+ const authMiddleware = options.authMiddleware;
10
+ router.post(`/:id`, async (req, res) => await CyberiaEntityController.post(req, res, options));
11
+ router.post(`/`, async (req, res) => await CyberiaEntityController.post(req, res, options));
12
+ router.get(
13
+ `/:id`,
14
+ // authMiddleware,
15
+ async (req, res) => await CyberiaEntityController.get(req, res, options),
16
+ );
17
+ router.get(`/`, async (req, res) => await CyberiaEntityController.get(req, res, options));
18
+ router.put(`/:id`, async (req, res) => await CyberiaEntityController.put(req, res, options));
19
+ router.put(`/`, async (req, res) => await CyberiaEntityController.put(req, res, options));
20
+ router.delete(`/:id`, async (req, res) => await CyberiaEntityController.delete(req, res, options));
21
+ router.delete(`/`, async (req, res) => await CyberiaEntityController.delete(req, res, options));
22
+ return router;
23
+ };
24
+
25
+ const ApiRouter = CyberiaEntityRouter;
26
+
27
+ export { ApiRouter, CyberiaEntityRouter };
@@ -0,0 +1,42 @@
1
+ import { DataBaseProvider } from '../../db/DataBaseProvider.js';
2
+ import { loggerFactory } from '../../server/logger.js';
3
+ import { DataQuery } from '../../server/data-query.js';
4
+
5
+ const logger = loggerFactory(import.meta);
6
+
7
+ const CyberiaEntityService = {
8
+ post: async (req, res, options) => {
9
+ /** @type {import('./cyberia-entity.model.js').CyberiaEntityModel} */
10
+ const CyberiaEntity = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaEntity;
11
+ return await new CyberiaEntity(req.body).save();
12
+ },
13
+ get: async (req, res, options) => {
14
+ /** @type {import('./cyberia-entity.model.js').CyberiaEntityModel} */
15
+ const CyberiaEntity = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaEntity;
16
+ if (req.params.id) return await CyberiaEntity.findById(req.params.id);
17
+
18
+ // Parse query parameters using DataQuery helper
19
+ const { query, sort, skip, limit, page } = DataQuery.parse(req.query);
20
+
21
+ const [data, total] = await Promise.all([
22
+ CyberiaEntity.find(query).sort(sort).limit(limit).skip(skip),
23
+ CyberiaEntity.countDocuments(query),
24
+ ]);
25
+
26
+ const totalPages = Math.ceil(total / limit);
27
+ return { data, total, page, totalPages };
28
+ },
29
+ put: async (req, res, options) => {
30
+ /** @type {import('./cyberia-entity.model.js').CyberiaEntityModel} */
31
+ const CyberiaEntity = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaEntity;
32
+ return await CyberiaEntity.findByIdAndUpdate(req.params.id, req.body);
33
+ },
34
+ delete: async (req, res, options) => {
35
+ /** @type {import('./cyberia-entity.model.js').CyberiaEntityModel} */
36
+ const CyberiaEntity = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaEntity;
37
+ if (req.params.id) return await CyberiaEntity.findByIdAndDelete(req.params.id);
38
+ else return await CyberiaEntity.deleteMany();
39
+ },
40
+ };
41
+
42
+ export { CyberiaEntityService };