cyberia 3.1.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 (208) hide show
  1. package/.env.example +0 -2
  2. package/.github/workflows/engine-cyberia.cd.yml +10 -8
  3. package/.github/workflows/engine-cyberia.ci.yml +12 -29
  4. package/.github/workflows/ghpkg.ci.yml +4 -4
  5. package/.github/workflows/npmpkg.ci.yml +28 -11
  6. package/.github/workflows/publish.ci.yml +21 -2
  7. package/.github/workflows/pwa-microservices-template-page.cd.yml +4 -5
  8. package/.github/workflows/pwa-microservices-template-test.ci.yml +3 -3
  9. package/.github/workflows/release.cd.yml +13 -8
  10. package/CHANGELOG.md +433 -1
  11. package/CLI-HELP.md +57 -7
  12. package/Dockerfile +4 -2
  13. package/README.md +347 -22
  14. package/bin/build.js +5 -2
  15. package/bin/cyberia.js +1789 -112
  16. package/bin/deploy.js +177 -124
  17. package/bin/file.js +3 -0
  18. package/bin/index.js +1789 -112
  19. package/conf.js +64 -8
  20. package/deployment.yaml +92 -20
  21. package/hardhat/hardhat.config.js +13 -13
  22. package/hardhat/ignition/modules/ObjectLayerToken.js +1 -1
  23. package/hardhat/package-lock.json +2554 -5859
  24. package/hardhat/package.json +13 -22
  25. package/hardhat/scripts/deployObjectLayerToken.js +1 -1
  26. package/hardhat/test/ObjectLayerToken.js +4 -2
  27. package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
  28. package/hardhat/types/ethers-contracts/common.ts +92 -0
  29. package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
  30. package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
  31. package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
  32. package/hardhat/types/ethers-contracts/index.ts +6 -0
  33. package/jsdoc.dd-cyberia.json +64 -55
  34. package/jsdoc.json +64 -55
  35. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +5 -4
  36. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +5 -4
  37. package/manifests/deployment/dd-cyberia-development/deployment.yaml +92 -20
  38. package/manifests/deployment/dd-cyberia-development/proxy.yaml +54 -18
  39. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  40. package/manifests/deployment/dd-test-development/deployment.yaml +88 -74
  41. package/manifests/deployment/dd-test-development/proxy.yaml +13 -4
  42. package/manifests/deployment/playwright/deployment.yaml +1 -1
  43. package/nodemon.json +1 -1
  44. package/package.json +22 -16
  45. package/proxy.yaml +54 -18
  46. package/scripts/rhel-grpc-setup.sh +56 -0
  47. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +44 -0
  48. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +16 -0
  49. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +5 -0
  50. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +80 -7
  51. package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +93 -0
  52. package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
  53. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +29 -0
  54. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +51 -0
  55. package/src/api/cyberia-entity/cyberia-entity.controller.js +74 -0
  56. package/src/api/cyberia-entity/cyberia-entity.model.js +24 -0
  57. package/src/api/cyberia-entity/cyberia-entity.router.js +27 -0
  58. package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
  59. package/src/api/cyberia-instance/cyberia-fallback-world.js +368 -0
  60. package/src/api/cyberia-instance/cyberia-instance.controller.js +92 -0
  61. package/src/api/cyberia-instance/cyberia-instance.model.js +84 -0
  62. package/src/api/cyberia-instance/cyberia-instance.router.js +63 -0
  63. package/src/api/cyberia-instance/cyberia-instance.service.js +191 -0
  64. package/src/api/cyberia-instance/cyberia-portal-connector.js +486 -0
  65. package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +74 -0
  66. package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +413 -0
  67. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +228 -0
  68. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +27 -0
  69. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +42 -0
  70. package/src/api/cyberia-map/cyberia-map.controller.js +79 -0
  71. package/src/api/cyberia-map/cyberia-map.model.js +30 -0
  72. package/src/api/cyberia-map/cyberia-map.router.js +40 -0
  73. package/src/api/cyberia-map/cyberia-map.service.js +74 -0
  74. package/src/api/file/file.ref.json +18 -0
  75. package/src/api/ipfs/ipfs.controller.js +4 -25
  76. package/src/api/ipfs/ipfs.model.js +43 -34
  77. package/src/api/ipfs/ipfs.router.js +8 -13
  78. package/src/api/ipfs/ipfs.service.js +54 -102
  79. package/src/api/object-layer/README.md +347 -22
  80. package/src/api/object-layer/object-layer.router.js +30 -0
  81. package/src/api/object-layer/object-layer.service.js +114 -31
  82. package/src/api/user/user.service.js +8 -7
  83. package/src/cli/cluster.js +7 -7
  84. package/src/cli/db.js +710 -827
  85. package/src/cli/deploy.js +151 -93
  86. package/src/cli/env.js +29 -0
  87. package/src/cli/fs.js +5 -2
  88. package/src/cli/index.js +48 -2
  89. package/src/cli/kubectl.js +211 -0
  90. package/src/cli/release.js +284 -0
  91. package/src/cli/repository.js +438 -75
  92. package/src/cli/run.js +195 -35
  93. package/src/cli/secrets.js +73 -0
  94. package/src/cli/test.js +3 -3
  95. package/src/client/Cryptokoyn.index.js +3 -4
  96. package/src/client/CyberiaPortal.index.js +3 -4
  97. package/src/client/Default.index.js +3 -4
  98. package/src/client/Itemledger.index.js +3 -4
  99. package/src/client/Underpost.index.js +3 -4
  100. package/src/client/components/core/AppStore.js +69 -0
  101. package/src/client/components/core/CalendarCore.js +2 -2
  102. package/src/client/components/core/DropDown.js +137 -17
  103. package/src/client/components/core/Keyboard.js +2 -2
  104. package/src/client/components/core/LogIn.js +2 -2
  105. package/src/client/components/core/LogOut.js +2 -2
  106. package/src/client/components/core/Modal.js +0 -1
  107. package/src/client/components/core/Panel.js +0 -1
  108. package/src/client/components/core/PanelForm.js +19 -19
  109. package/src/client/components/core/SocketIo.js +82 -29
  110. package/src/client/components/core/SocketIoHandler.js +75 -0
  111. package/src/client/components/core/Stream.js +143 -95
  112. package/src/client/components/core/Webhook.js +40 -7
  113. package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
  114. package/src/client/components/cryptokoyn/LogInCryptokoyn.js +3 -3
  115. package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +2 -2
  116. package/src/client/components/cryptokoyn/MenuCryptokoyn.js +3 -3
  117. package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +3 -51
  118. package/src/client/components/cyberia/InstanceEngineCyberia.js +700 -0
  119. package/src/client/components/cyberia/MapEngineCyberia.js +1359 -2
  120. package/src/client/components/cyberia/ObjectLayerEngineModal.js +17 -6
  121. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +92 -54
  122. package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
  123. package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +216 -30
  124. package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +3 -3
  125. package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +2 -2
  126. package/src/client/components/cyberia-portal/MenuCyberiaPortal.js +40 -7
  127. package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +4 -0
  128. package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +3 -49
  129. package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
  130. package/src/client/components/default/AppStoreDefault.js +5 -0
  131. package/src/client/components/default/LogInDefault.js +3 -3
  132. package/src/client/components/default/LogOutDefault.js +2 -2
  133. package/src/client/components/default/MenuDefault.js +5 -5
  134. package/src/client/components/default/SocketIoDefault.js +3 -51
  135. package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
  136. package/src/client/components/itemledger/LogInItemledger.js +3 -3
  137. package/src/client/components/itemledger/LogOutItemledger.js +2 -2
  138. package/src/client/components/itemledger/MenuItemledger.js +3 -3
  139. package/src/client/components/itemledger/SocketIoItemledger.js +3 -51
  140. package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
  141. package/src/client/components/underpost/LogInUnderpost.js +3 -3
  142. package/src/client/components/underpost/LogOutUnderpost.js +2 -2
  143. package/src/client/components/underpost/MenuUnderpost.js +5 -5
  144. package/src/client/components/underpost/SocketIoUnderpost.js +3 -51
  145. package/src/client/services/core/core.service.js +20 -8
  146. package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +105 -0
  147. package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
  148. package/src/client/services/cyberia-entity/cyberia-entity.service.js +105 -0
  149. package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
  150. package/src/client/services/cyberia-instance/cyberia-instance.service.js +122 -0
  151. package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +105 -0
  152. package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
  153. package/src/client/services/cyberia-map/cyberia-map.service.js +126 -0
  154. package/src/client/services/instance/instance.management.js +2 -2
  155. package/src/client/services/ipfs/ipfs.service.js +3 -23
  156. package/src/client/services/object-layer/object-layer.management.js +3 -3
  157. package/src/client/services/object-layer/object-layer.service.js +21 -0
  158. package/src/client/services/user/user.management.js +2 -2
  159. package/src/client/ssr/pages/CyberiaServerMetrics.js +1 -1
  160. package/src/grpc/cyberia/OFF_CHAIN_ECONOMY.md +305 -0
  161. package/src/grpc/cyberia/README.md +326 -0
  162. package/src/grpc/cyberia/grpc-server.js +530 -0
  163. package/src/index.js +24 -1
  164. package/src/runtime/express/Dockerfile +4 -0
  165. package/src/runtime/express/Express.js +18 -1
  166. package/src/runtime/lampp/Dockerfile +13 -2
  167. package/src/runtime/lampp/Lampp.js +27 -4
  168. package/src/runtime/wp/Dockerfile +68 -0
  169. package/src/runtime/wp/Wp.js +639 -0
  170. package/src/server/auth.js +24 -1
  171. package/src/server/backup.js +37 -9
  172. package/src/server/client-build-docs.js +9 -2
  173. package/src/server/client-build.js +31 -31
  174. package/src/server/client-formatted.js +109 -57
  175. package/src/server/conf.js +24 -9
  176. package/src/server/cron.js +25 -23
  177. package/src/server/dns.js +2 -1
  178. package/src/server/ipfs-client.js +24 -1
  179. package/src/server/object-layer.js +149 -108
  180. package/src/server/peer.js +8 -0
  181. package/src/server/runtime.js +25 -1
  182. package/src/server/semantic-layer-generator-floor.js +359 -0
  183. package/src/server/semantic-layer-generator-skin.js +1294 -0
  184. package/src/server/semantic-layer-generator.js +116 -555
  185. package/src/server/start.js +2 -2
  186. package/src/ws/IoInterface.js +1 -10
  187. package/src/ws/IoServer.js +14 -33
  188. package/src/ws/core/channels/core.ws.chat.js +65 -20
  189. package/src/ws/core/channels/core.ws.mailer.js +113 -32
  190. package/src/ws/core/channels/core.ws.stream.js +90 -31
  191. package/src/ws/core/core.ws.connection.js +12 -33
  192. package/src/ws/core/core.ws.emit.js +10 -26
  193. package/src/ws/core/core.ws.server.js +25 -58
  194. package/src/ws/default/channels/default.ws.main.js +53 -12
  195. package/src/ws/default/default.ws.connection.js +26 -13
  196. package/src/ws/default/default.ws.server.js +30 -12
  197. package/src/client/components/cryptokoyn/CommonCryptokoyn.js +0 -29
  198. package/src/client/components/cryptokoyn/ElementsCryptokoyn.js +0 -38
  199. package/src/client/components/cyberia-portal/ElementsCyberiaPortal.js +0 -38
  200. package/src/client/components/default/ElementsDefault.js +0 -38
  201. package/src/client/components/itemledger/CommonItemledger.js +0 -29
  202. package/src/client/components/itemledger/ElementsItemledger.js +0 -38
  203. package/src/client/components/underpost/CommonUnderpost.js +0 -29
  204. package/src/client/components/underpost/ElementsUnderpost.js +0 -38
  205. package/src/ws/core/management/core.ws.chat.js +0 -8
  206. package/src/ws/core/management/core.ws.mailer.js +0 -16
  207. package/src/ws/core/management/core.ws.stream.js +0 -8
  208. package/src/ws/default/management/default.ws.main.js +0 -8
@@ -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 CyberiaInstanceConfService = {
8
+ post: async (req, res, options) => {
9
+ /** @type {import('./cyberia-instance-conf.model.js').CyberiaInstanceConfModel} */
10
+ const CyberiaInstanceConf = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaInstanceConf;
11
+ return await new CyberiaInstanceConf(req.body).save();
12
+ },
13
+ get: async (req, res, options) => {
14
+ /** @type {import('./cyberia-instance-conf.model.js').CyberiaInstanceConfModel} */
15
+ const CyberiaInstanceConf = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaInstanceConf;
16
+ if (req.params.id) return await CyberiaInstanceConf.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
+ CyberiaInstanceConf.find(query).sort(sort).limit(limit).skip(skip),
23
+ CyberiaInstanceConf.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-instance-conf.model.js').CyberiaInstanceConfModel} */
31
+ const CyberiaInstanceConf = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaInstanceConf;
32
+ return await CyberiaInstanceConf.findByIdAndUpdate(req.params.id, req.body);
33
+ },
34
+ delete: async (req, res, options) => {
35
+ /** @type {import('./cyberia-instance-conf.model.js').CyberiaInstanceConfModel} */
36
+ const CyberiaInstanceConf = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaInstanceConf;
37
+ if (req.params.id) return await CyberiaInstanceConf.findByIdAndDelete(req.params.id);
38
+ else return await CyberiaInstanceConf.deleteMany();
39
+ },
40
+ };
41
+
42
+ export { CyberiaInstanceConfService };
@@ -0,0 +1,79 @@
1
+ import { loggerFactory } from '../../server/logger.js';
2
+ import { CyberiaMapService } from './cyberia-map.service.js';
3
+
4
+ const logger = loggerFactory(import.meta);
5
+
6
+ const CyberiaMapController = {
7
+ post: async (req, res, options) => {
8
+ try {
9
+ const result = await CyberiaMapService.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 CyberiaMapService.get(
26
+ {
27
+ ...req,
28
+ path: req.path,
29
+ params: req.params,
30
+ query: { ...req.query, page: parseInt(page), limit: parseInt(limit) },
31
+ },
32
+ res,
33
+ options,
34
+ );
35
+ return res.status(200).json({
36
+ status: 'success',
37
+ data: result,
38
+ });
39
+ } catch (error) {
40
+ logger.error(error, error.stack);
41
+ return res.status(400).json({
42
+ status: 'error',
43
+ message: error.message,
44
+ });
45
+ }
46
+ },
47
+ put: async (req, res, options) => {
48
+ try {
49
+ const result = await CyberiaMapService.put(req, res, options);
50
+ return res.status(200).json({
51
+ status: 'success',
52
+ data: result,
53
+ });
54
+ } catch (error) {
55
+ logger.error(error, error.stack);
56
+ return res.status(400).json({
57
+ status: 'error',
58
+ message: error.message,
59
+ });
60
+ }
61
+ },
62
+ delete: async (req, res, options) => {
63
+ try {
64
+ const result = await CyberiaMapService.delete(req, res, options);
65
+ return res.status(200).json({
66
+ status: 'success',
67
+ data: result,
68
+ });
69
+ } catch (error) {
70
+ logger.error(error, error.stack);
71
+ return res.status(400).json({
72
+ status: 'error',
73
+ message: error.message,
74
+ });
75
+ }
76
+ },
77
+ };
78
+
79
+ export { CyberiaMapController };
@@ -0,0 +1,30 @@
1
+ import { Schema, model, Types } from 'mongoose';
2
+ import { CyberiaEntitySchema } from '../cyberia-entity/cyberia-entity.model.js';
3
+
4
+ // https://mongoosejs.com/docs/2.7.x/docs/schematypes.html
5
+
6
+ const CyberiaMapSchema = new Schema(
7
+ {
8
+ code: { type: String, default: '', unique: true },
9
+ name: { type: String, default: '' },
10
+ description: { type: String, default: '' },
11
+ entities: { type: [CyberiaEntitySchema], default: [] },
12
+ tags: { type: [String], default: [] },
13
+ creator: { type: Schema.Types.ObjectId, ref: 'User' },
14
+ status: { type: String, default: 'unlisted' },
15
+ thumbnail: { type: Schema.Types.ObjectId, ref: 'File' },
16
+ gridX: { type: Number, default: 16 },
17
+ gridY: { type: Number, default: 16 },
18
+ cellWidth: { type: Number, default: 32 },
19
+ cellHeight: { type: Number, default: 32 },
20
+ },
21
+ {
22
+ timestamps: true,
23
+ },
24
+ );
25
+
26
+ const CyberiaMapModel = model('CyberiaMap', CyberiaMapSchema);
27
+
28
+ const ProviderSchema = CyberiaMapSchema;
29
+
30
+ export { CyberiaMapSchema, CyberiaMapModel, ProviderSchema };
@@ -0,0 +1,40 @@
1
+ import { loggerFactory } from '../../server/logger.js';
2
+ import { CyberiaMapController } from './cyberia-map.controller.js';
3
+ import { userGuard, adminGuard } from '../../server/auth.js';
4
+ import express from 'express';
5
+
6
+ const logger = loggerFactory(import.meta);
7
+
8
+ const CyberiaMapRouter = (options) => {
9
+ const router = express.Router();
10
+ const authMiddleware = options.authMiddleware;
11
+ router.post(
12
+ `/:id`,
13
+ authMiddleware,
14
+ userGuard,
15
+ async (req, res) => await CyberiaMapController.post(req, res, options),
16
+ );
17
+ router.post(`/`, authMiddleware, userGuard, async (req, res) => await CyberiaMapController.post(req, res, options));
18
+ router.get(`/search-codes`, async (req, res) => await CyberiaMapController.get(req, res, options));
19
+ router.get(`/:id`, async (req, res) => await CyberiaMapController.get(req, res, options));
20
+ router.get(`/`, async (req, res) => await CyberiaMapController.get(req, res, options));
21
+ router.put(`/:id`, authMiddleware, userGuard, async (req, res) => await CyberiaMapController.put(req, res, options));
22
+ router.put(`/`, authMiddleware, userGuard, async (req, res) => await CyberiaMapController.put(req, res, options));
23
+ router.delete(
24
+ `/:id`,
25
+ authMiddleware,
26
+ userGuard,
27
+ async (req, res) => await CyberiaMapController.delete(req, res, options),
28
+ );
29
+ router.delete(
30
+ `/`,
31
+ authMiddleware,
32
+ adminGuard,
33
+ async (req, res) => await CyberiaMapController.delete(req, res, options),
34
+ );
35
+ return router;
36
+ };
37
+
38
+ const ApiRouter = CyberiaMapRouter;
39
+
40
+ export { ApiRouter, CyberiaMapRouter };
@@ -0,0 +1,74 @@
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 CyberiaMapService = {
8
+ post: async (req, res, options) => {
9
+ /** @type {import('./cyberia-map.model.js').CyberiaMapModel} */
10
+ const CyberiaMap = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaMap;
11
+ if (req.auth && req.auth.user) req.body.creator = req.auth.user._id;
12
+ return await new CyberiaMap(req.body).save();
13
+ },
14
+ get: async (req, res, options) => {
15
+ /** @type {import('./cyberia-map.model.js').CyberiaMapModel} */
16
+ const CyberiaMap = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaMap;
17
+ const populateCreator = { path: 'creator', model: 'User', select: '_id username' };
18
+
19
+ // GET /search-codes?q=<partial> - Fast partial match search on code
20
+ if (req.path?.startsWith('/search-codes')) {
21
+ const q = (req.query.q || '').trim();
22
+ if (!q) return { codes: [] };
23
+ const escaped = q.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
24
+ const results = await CyberiaMap.find({ code: { $regex: escaped, $options: 'i' } }, { code: 1, _id: 0 })
25
+ .limit(20)
26
+ .lean();
27
+ const codes = [...new Set(results.map((r) => r.code).filter(Boolean))];
28
+ return { codes };
29
+ }
30
+
31
+ if (req.params.id) return await CyberiaMap.findById(req.params.id).populate(populateCreator);
32
+
33
+ // Parse query parameters using DataQuery helper
34
+ const { query, sort, skip, limit, page } = DataQuery.parse(req.query);
35
+
36
+ const [data, total] = await Promise.all([
37
+ CyberiaMap.find(query).sort(sort).limit(limit).skip(skip).populate(populateCreator),
38
+ CyberiaMap.countDocuments(query),
39
+ ]);
40
+
41
+ const totalPages = Math.ceil(total / limit);
42
+ return { data, total, page, totalPages };
43
+ },
44
+ put: async (req, res, options) => {
45
+ /** @type {import('./cyberia-map.model.js').CyberiaMapModel} */
46
+ const CyberiaMap = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaMap;
47
+ const map = await CyberiaMap.findById(req.params.id);
48
+ if (!map) throw new Error('map not found');
49
+ if (req.auth.user.role !== 'admin' && String(map.creator) !== String(req.auth.user._id))
50
+ throw new Error('insufficient permission');
51
+ if (req.body.thumbnail && map.thumbnail && String(req.body.thumbnail) !== String(map.thumbnail)) {
52
+ const File = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.File;
53
+ await File.findByIdAndDelete(map.thumbnail);
54
+ }
55
+ return await CyberiaMap.findByIdAndUpdate(req.params.id, req.body, { returnDocument: 'after' });
56
+ },
57
+ delete: async (req, res, options) => {
58
+ /** @type {import('./cyberia-map.model.js').CyberiaMapModel} */
59
+ const CyberiaMap = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.CyberiaMap;
60
+ if (req.params.id) {
61
+ const map = await CyberiaMap.findById(req.params.id);
62
+ if (!map) throw new Error('map not found');
63
+ if (req.auth.user.role !== 'admin' && String(map.creator) !== String(req.auth.user._id))
64
+ throw new Error('insufficient permission');
65
+ if (map.thumbnail) {
66
+ const File = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.File;
67
+ await File.findByIdAndDelete(map.thumbnail);
68
+ }
69
+ return await CyberiaMap.findByIdAndDelete(req.params.id);
70
+ } else return await CyberiaMap.deleteMany();
71
+ },
72
+ };
73
+
74
+ export { CyberiaMapService };
@@ -1,10 +1,28 @@
1
1
  [
2
+ {
3
+ "api": "atlas-sprite-sheet",
4
+ "model": {
5
+ "fileId": true
6
+ }
7
+ },
2
8
  {
3
9
  "api": "company",
4
10
  "model": {
5
11
  "logo": true
6
12
  }
7
13
  },
14
+ {
15
+ "api": "cyberia-instance",
16
+ "model": {
17
+ "thumbnail": true
18
+ }
19
+ },
20
+ {
21
+ "api": "cyberia-map",
22
+ "model": {
23
+ "thumbnail": true
24
+ }
25
+ },
8
26
  {
9
27
  "api": "document",
10
28
  "model": {
@@ -69,34 +69,13 @@ const IpfsController = {
69
69
  });
70
70
  }
71
71
  },
72
- pin: async (req, res, options) => {
72
+ verify: async (req, res, options) => {
73
73
  try {
74
- const result = await IpfsService.pin(req, res, options);
75
- return res.status(200).json({
76
- status: 'success',
77
- data: result,
78
- });
74
+ const result = await IpfsService.verify(req, res, options);
75
+ return res.status(200).json({ status: 'success', data: result });
79
76
  } catch (error) {
80
77
  logger.error(error, error.stack);
81
- return res.status(400).json({
82
- status: 'error',
83
- message: error.message,
84
- });
85
- }
86
- },
87
- unpin: async (req, res, options) => {
88
- try {
89
- const result = await IpfsService.unpin(req, res, options);
90
- return res.status(200).json({
91
- status: 'success',
92
- data: result,
93
- });
94
- } catch (error) {
95
- logger.error(error, error.stack);
96
- return res.status(400).json({
97
- status: 'error',
98
- message: error.message,
99
- });
78
+ return res.status(400).json({ status: 'error', message: error.message });
100
79
  }
101
80
  },
102
81
  };
@@ -1,6 +1,22 @@
1
1
  /**
2
- * Mongoose model for IPFS API – a general-purpose pin record that relates
3
- * a user to a CID.
2
+ * Mongoose model for the IPFS CID Registry.
3
+ *
4
+ * Purpose: tracks every CID that the Engine has pinned to IPFS so that:
5
+ * 1. Deletions can cleanly unpin the right CID from the IPFS node/cluster.
6
+ * 2. Admins can run a health-check that verifies every DB-registered CID is
7
+ * still actually pinned (GET /ipfs/verify).
8
+ * 3. Garbage-collection jobs can discover orphaned CIDs (pinned on the node
9
+ * but not referenced by any DB document).
10
+ *
11
+ * Fields:
12
+ * cid - IPFS Content Identifier (CIDv0 or CIDv1).
13
+ * resourceType - What kind of asset this CID belongs to:
14
+ * 'object-layer-data' - JSON payload of an ObjectLayer document.
15
+ * 'atlas-sprite-sheet' - PNG sprite-sheet of an ObjectLayer.
16
+ * 'atlas-metadata' - JSON metadata of an AtlasSpriteSheet.
17
+ * mfsPath - MFS (Mutable File System) path used when the CID was added,
18
+ * e.g. /object-layer/sword/sword_data.json.
19
+ * Enables targeted removal via files/rm without knowing the CID.
4
20
  *
5
21
  * @module src/api/ipfs/ipfs.model.js
6
22
  * @namespace IpfsModel
@@ -8,14 +24,6 @@
8
24
 
9
25
  import { Schema, model } from 'mongoose';
10
26
 
11
- /**
12
- * @typedef {Object} Ipfs
13
- * @property {string} cid – IPFS Content Identifier (CIDv0 or CIDv1).
14
- * @property {Types.ObjectId} userId – Reference to the User who owns / requested the pin.
15
- * @property {Date} createdAt – Auto-managed by Mongoose.
16
- * @property {Date} updatedAt – Auto-managed by Mongoose.
17
- * @memberof IpfsModel
18
- */
19
27
  const IpfsSchema = new Schema(
20
28
  {
21
29
  cid: {
@@ -23,10 +31,19 @@ const IpfsSchema = new Schema(
23
31
  required: true,
24
32
  trim: true,
25
33
  },
26
- userId: {
27
- type: Schema.Types.ObjectId,
28
- ref: 'User',
34
+ // Asset category - determines which service owns this CID.
35
+ resourceType: {
36
+ type: String,
29
37
  required: true,
38
+ trim: true,
39
+ enum: ['object-layer-data', 'atlas-sprite-sheet', 'atlas-metadata'],
40
+ },
41
+ // MFS path used when the content was added to IPFS.
42
+ // Empty string when the content was added without an MFS copy.
43
+ mfsPath: {
44
+ type: String,
45
+ default: '',
46
+ trim: true,
30
47
  },
31
48
  },
32
49
  {
@@ -34,14 +51,14 @@ const IpfsSchema = new Schema(
34
51
  },
35
52
  );
36
53
 
37
- // Compound index: one pin record per user + CID pair.
38
- IpfsSchema.index({ cid: 1, userId: 1 }, { unique: true });
54
+ // One DB record per (CID, resourceType) pair.
55
+ IpfsSchema.index({ cid: 1, resourceType: 1 }, { unique: true });
39
56
 
40
- // Fast look-ups by user.
41
- IpfsSchema.index({ userId: 1 });
57
+ // Fast look-ups for health-check and garbage-collection by type.
58
+ IpfsSchema.index({ resourceType: 1 });
42
59
 
43
- // Fast look-ups by CID.
44
- IpfsSchema.index({ cid: 1 });
60
+ // Fast look-ups for targeted MFS cleanup.
61
+ IpfsSchema.index({ mfsPath: 1 });
45
62
 
46
63
  const IpfsModel = model('Ipfs', IpfsSchema);
47
64
 
@@ -49,21 +66,13 @@ const ProviderSchema = IpfsSchema;
49
66
 
50
67
  const IpfsDto = {
51
68
  select: {
52
- get: () => {
53
- return {
54
- _id: 1,
55
- cid: 1,
56
- userId: 1,
57
- createdAt: 1,
58
- updatedAt: 1,
59
- };
60
- },
61
- },
62
- populate: {
63
- user: () => ({
64
- path: 'userId',
65
- model: 'User',
66
- select: '_id username email role',
69
+ get: () => ({
70
+ _id: 1,
71
+ cid: 1,
72
+ resourceType: 1,
73
+ mfsPath: 1,
74
+ createdAt: 1,
75
+ updatedAt: 1,
67
76
  }),
68
77
  },
69
78
  };
@@ -8,19 +8,14 @@ const logger = loggerFactory(import.meta);
8
8
  const IpfsRouter = (options) => {
9
9
  const router = express.Router();
10
10
  const authMiddleware = options.authMiddleware;
11
- router.post(`/pin`, authMiddleware, adminGuard, async (req, res) => await IpfsController.pin(req, res, options));
12
- router.delete(
13
- `/pin/:cid`,
14
- authMiddleware,
15
- adminGuard,
16
- async (req, res) => await IpfsController.unpin(req, res, options),
17
- );
18
- router.post(`/:id`, authMiddleware, async (req, res) => await IpfsController.post(req, res, options));
19
- router.post(`/`, authMiddleware, async (req, res) => await IpfsController.post(req, res, options));
20
- router.get(`/:id`, authMiddleware, async (req, res) => await IpfsController.get(req, res, options));
21
- router.get(`/`, authMiddleware, async (req, res) => await IpfsController.get(req, res, options));
22
- router.put(`/:id`, authMiddleware, async (req, res) => await IpfsController.put(req, res, options));
23
- router.put(`/`, authMiddleware, async (req, res) => await IpfsController.put(req, res, options));
11
+ // Health / audit must come before /:id to avoid matching conflicts.
12
+ router.get(`/verify`, authMiddleware, adminGuard, async (req, res) => await IpfsController.verify(req, res, options));
13
+ router.post(`/:id`, authMiddleware, adminGuard, async (req, res) => await IpfsController.post(req, res, options));
14
+ router.post(`/`, authMiddleware, adminGuard, async (req, res) => await IpfsController.post(req, res, options));
15
+ router.get(`/:id`, authMiddleware, adminGuard, async (req, res) => await IpfsController.get(req, res, options));
16
+ router.get(`/`, authMiddleware, adminGuard, async (req, res) => await IpfsController.get(req, res, options));
17
+ router.put(`/:id`, authMiddleware, adminGuard, async (req, res) => await IpfsController.put(req, res, options));
18
+ router.put(`/`, authMiddleware, adminGuard, async (req, res) => await IpfsController.put(req, res, options));
24
19
  router.delete(`/:id`, authMiddleware, adminGuard, async (req, res) => await IpfsController.delete(req, res, options));
25
20
  router.delete(`/`, authMiddleware, adminGuard, async (req, res) => await IpfsController.delete(req, res, options));
26
21
  return router;