cyberia 3.2.9 → 3.2.12

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 (169) hide show
  1. package/.github/workflows/engine-cyberia.cd.yml +6 -0
  2. package/.github/workflows/npmpkg.ci.yml +1 -0
  3. package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
  4. package/.github/workflows/release.cd.yml +1 -0
  5. package/.vscode/extensions.json +9 -9
  6. package/.vscode/settings.json +20 -4
  7. package/CHANGELOG.md +213 -1
  8. package/CLI-HELP.md +92 -23
  9. package/README.md +190 -348
  10. package/bin/build.js +24 -8
  11. package/bin/build.template.js +187 -0
  12. package/bin/cyberia.js +229 -52
  13. package/bin/deploy.js +12 -2
  14. package/bin/index.js +229 -52
  15. package/bump.config.js +26 -0
  16. package/conf.js +130 -24
  17. package/deployment.yaml +4 -2
  18. package/hardhat/package-lock.json +113 -144
  19. package/hardhat/package.json +4 -3
  20. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  21. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  22. package/manifests/deployment/dd-cyberia-development/deployment.yaml +4 -2
  23. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  24. package/manifests/deployment/dd-test-development/deployment.yaml +4 -2
  25. package/manifests/kind-config-dev.yaml +8 -0
  26. package/manifests/lxd/lxd-admin-profile.yaml +12 -3
  27. package/manifests/mongodb/pv-pvc.yaml +44 -8
  28. package/manifests/mongodb/statefulset.yaml +55 -68
  29. package/manifests/mongodb-4.4/headless-service.yaml +10 -0
  30. package/manifests/mongodb-4.4/kustomization.yaml +3 -1
  31. package/manifests/mongodb-4.4/mongodb-nodeport.yaml +17 -0
  32. package/manifests/mongodb-4.4/pv-pvc.yaml +10 -14
  33. package/manifests/mongodb-4.4/statefulset.yaml +79 -0
  34. package/manifests/mongodb-4.4/storage-class.yaml +9 -0
  35. package/manifests/valkey/statefulset.yaml +1 -1
  36. package/manifests/valkey/valkey-nodeport.yaml +17 -0
  37. package/package.json +27 -15
  38. package/scripts/ipxe-setup.sh +52 -49
  39. package/scripts/k3s-node-setup.sh +81 -46
  40. package/scripts/lxd-vm-setup.sh +193 -8
  41. package/scripts/maas-nat-firewalld.sh +145 -0
  42. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +38 -33
  43. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +16 -16
  44. package/src/api/core/core.router.js +19 -14
  45. package/src/api/core/core.service.js +5 -5
  46. package/src/api/crypto/crypto.router.js +18 -12
  47. package/src/api/crypto/crypto.service.js +3 -3
  48. package/src/api/cyberia-action/cyberia-action.model.js +1 -1
  49. package/src/api/cyberia-action/cyberia-action.router.js +22 -18
  50. package/src/api/cyberia-action/cyberia-action.service.js +5 -5
  51. package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +74 -0
  52. package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +99 -0
  53. package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +98 -0
  54. package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +152 -0
  55. package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +25 -20
  56. package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +6 -6
  57. package/src/api/cyberia-entity/cyberia-entity.router.js +22 -18
  58. package/src/api/cyberia-entity/cyberia-entity.service.js +5 -5
  59. package/src/api/cyberia-instance/cyberia-fallback-world.js +79 -4
  60. package/src/api/cyberia-instance/cyberia-instance.router.js +57 -52
  61. package/src/api/cyberia-instance/cyberia-instance.service.js +10 -10
  62. package/src/api/cyberia-instance/cyberia-world-generator.js +3 -3
  63. package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +14 -48
  64. package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +22 -18
  65. package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +5 -5
  66. package/src/api/cyberia-map/cyberia-map.router.js +35 -30
  67. package/src/api/cyberia-map/cyberia-map.service.js +7 -7
  68. package/src/api/cyberia-quest/cyberia-quest.model.js +1 -1
  69. package/src/api/cyberia-quest/cyberia-quest.router.js +22 -18
  70. package/src/api/cyberia-quest/cyberia-quest.service.js +5 -5
  71. package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +22 -18
  72. package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +5 -5
  73. package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +451 -0
  74. package/src/api/default/default.router.js +22 -18
  75. package/src/api/default/default.service.js +5 -5
  76. package/src/api/document/document.router.js +28 -23
  77. package/src/api/document/document.service.js +100 -23
  78. package/src/api/file/file.router.js +19 -13
  79. package/src/api/file/file.service.js +9 -7
  80. package/src/api/instance/instance.router.js +29 -24
  81. package/src/api/instance/instance.service.js +6 -6
  82. package/src/api/ipfs/ipfs.router.js +21 -16
  83. package/src/api/ipfs/ipfs.service.js +8 -8
  84. package/src/api/object-layer/object-layer.router.js +512 -507
  85. package/src/api/object-layer/object-layer.service.js +17 -14
  86. package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +22 -18
  87. package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +5 -5
  88. package/src/api/test/test.router.js +17 -12
  89. package/src/api/types.js +24 -0
  90. package/src/api/user/guest.service.js +5 -4
  91. package/src/api/user/user.router.js +297 -288
  92. package/src/api/user/user.service.js +100 -35
  93. package/src/cli/baremetal.js +132 -101
  94. package/src/cli/cluster.js +700 -232
  95. package/src/cli/db.js +59 -60
  96. package/src/cli/deploy.js +216 -137
  97. package/src/cli/fs.js +13 -3
  98. package/src/cli/index.js +80 -15
  99. package/src/cli/ipfs.js +4 -6
  100. package/src/cli/kubectl.js +4 -1
  101. package/src/cli/lxd.js +1099 -223
  102. package/src/cli/monitor.js +9 -3
  103. package/src/cli/release.js +334 -140
  104. package/src/cli/repository.js +68 -23
  105. package/src/cli/run.js +193 -49
  106. package/src/cli/secrets.js +11 -2
  107. package/src/cli/test.js +9 -3
  108. package/src/client/Default.index.js +9 -3
  109. package/src/client/components/core/Auth.js +5 -0
  110. package/src/client/components/core/ClientEvents.js +76 -0
  111. package/src/client/components/core/EventBus.js +4 -0
  112. package/src/client/components/core/Modal.js +82 -41
  113. package/src/client/components/core/PanelForm.js +56 -52
  114. package/src/client/components/core/Worker.js +162 -363
  115. package/src/client/components/cyberia/MapEngineCyberia.js +1 -1
  116. package/src/client/components/cyberia/SharedDefaultsCyberia.js +330 -0
  117. package/src/client/public/cyberia-docs/ARCHITECTURE.md +50 -410
  118. package/src/client/public/cyberia-docs/CYBERIA-CLI.md +114 -327
  119. package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +200 -222
  120. package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +203 -185
  121. package/src/client/public/cyberia-docs/CYBERIA.md +259 -0
  122. package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +2 -2
  123. package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
  124. package/src/client/public/cyberia-docs/UNDERPOST-PLATFORM.md +106 -0
  125. package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
  126. package/src/client/services/cyberia-client-hints/cyberia-client-hints.service.js +99 -0
  127. package/src/client/ssr/views/CyberiaServerMetrics.js +982 -0
  128. package/src/client/sw/core.sw.js +174 -112
  129. package/src/db/DataBaseProvider.js +115 -15
  130. package/src/db/mariadb/MariaDB.js +2 -1
  131. package/src/db/mongo/MongoBootstrap.js +657 -0
  132. package/src/db/mongo/MongooseDB.js +129 -21
  133. package/src/grpc/cyberia/grpc-server.js +25 -57
  134. package/src/index.js +1 -1
  135. package/src/runtime/cyberia-client/Dockerfile +24 -3
  136. package/src/runtime/cyberia-client/Dockerfile.dev +82 -0
  137. package/src/runtime/cyberia-server/Dockerfile +29 -4
  138. package/src/runtime/cyberia-server/Dockerfile.dev +71 -0
  139. package/src/runtime/express/Express.js +2 -2
  140. package/src/runtime/wp/Wp.js +8 -5
  141. package/src/server/auth.js +2 -2
  142. package/src/server/client-build-docs.js +1 -1
  143. package/src/server/client-build.js +94 -129
  144. package/src/server/conf.js +86 -83
  145. package/src/server/process.js +180 -19
  146. package/src/server/proxy.js +9 -2
  147. package/src/server/runtime.js +1 -1
  148. package/src/server/start.js +17 -5
  149. package/src/server/valkey.js +2 -0
  150. package/src/ws/IoInterface.js +16 -16
  151. package/src/ws/core/channels/core.ws.chat.js +11 -11
  152. package/src/ws/core/channels/core.ws.mailer.js +29 -29
  153. package/src/ws/core/channels/core.ws.stream.js +19 -19
  154. package/src/ws/core/core.ws.connection.js +8 -8
  155. package/src/ws/core/core.ws.server.js +6 -5
  156. package/src/ws/default/channels/default.ws.main.js +10 -10
  157. package/src/ws/default/default.ws.connection.js +4 -4
  158. package/src/ws/default/default.ws.server.js +4 -3
  159. package/bin/file.js +0 -202
  160. package/bin/vs.js +0 -74
  161. package/bin/zed.js +0 -84
  162. package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +0 -574
  163. package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +0 -467
  164. package/src/client/ssr/email/DefaultRecoverEmail.js +0 -21
  165. package/src/client/ssr/email/DefaultVerifyEmail.js +0 -17
  166. package/src/client/ssr/pages/CyberiaServerMetrics.js +0 -461
  167. /package/src/client/ssr/{offline → views}/Maintenance.js +0 -0
  168. /package/src/client/ssr/{offline → views}/NoNetworkConnection.js +0 -0
  169. /package/src/client/ssr/{pages → views}/Test.js +0 -0
@@ -10,7 +10,7 @@
10
10
  * @namespace CyberiaObjectLayerService
11
11
  */
12
12
 
13
- import { DataBaseProvider } from '../../db/DataBaseProvider.js';
13
+ import { DataBaseProviderService } from '../../db/DataBaseProvider.js';
14
14
  import { loggerFactory } from '../../server/logger.js';
15
15
  import { ObjectLayerRenderFramesDto } from '../object-layer-render-frames/object-layer-render-frames.model.js';
16
16
  import { FileFactory } from '../file/file.service.js';
@@ -149,9 +149,9 @@ class ObjectLayerService {
149
149
  fs.writeFileSync(`${publicFolder}/metadata.json`, metadataContent);
150
150
 
151
151
  // Build object layer data from the asset directory
152
- const ObjectLayer = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayer;
152
+ const ObjectLayer = DataBaseProviderService.getModel("ObjectLayer", options);
153
153
  const ObjectLayerRenderFrames =
154
- DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayerRenderFrames;
154
+ DataBaseProviderService.getModel("ObjectLayerRenderFrames", options);
155
155
 
156
156
  const { objectLayerRenderFramesData, objectLayerData } =
157
157
  await ObjectLayerEngine.buildObjectLayerDataFromDirectory({
@@ -183,9 +183,9 @@ class ObjectLayerService {
183
183
  }
184
184
 
185
185
  // create object layer from body – cut-over consistency: stage all CIDs before writing to DB
186
- const ObjectLayer = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayer;
186
+ const ObjectLayer = DataBaseProviderService.getModel("ObjectLayer", options);
187
187
  const ObjectLayerRenderFrames =
188
- DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayerRenderFrames;
188
+ DataBaseProviderService.getModel("ObjectLayerRenderFrames", options);
189
189
 
190
190
  const bodyData = { ...req.body };
191
191
  if (!bodyData.data) bodyData.data = {};
@@ -270,7 +270,7 @@ class ObjectLayerService {
270
270
  */
271
271
  static get = async (req, res, options) => {
272
272
  /** @type {import('./object-layer.model.js').ObjectLayerModel} */
273
- const ObjectLayer = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayer;
273
+ const ObjectLayer = DataBaseProviderService.getModel("ObjectLayer", options);
274
274
 
275
275
  // GET /search-item-ids?q=<partial> - Fast partial match search on data.item.id
276
276
  if (req.path.startsWith('/search-item-ids')) {
@@ -360,8 +360,8 @@ class ObjectLayerService {
360
360
  if (objectLayer.atlasSpriteSheetId) {
361
361
  try {
362
362
  const AtlasSpriteSheet =
363
- DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.AtlasSpriteSheet;
364
- const File = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.File;
363
+ DataBaseProviderService.getModel("AtlasSpriteSheet", options);
364
+ const File = DataBaseProviderService.getModel("File", options);
365
365
 
366
366
  const atlasDoc = await AtlasSpriteSheet.findById(objectLayer.atlasSpriteSheetId);
367
367
 
@@ -451,7 +451,7 @@ class ObjectLayerService {
451
451
  */
452
452
  static generateWebp = async (req, res, options) => {
453
453
  /** @type {import('./object-layer.model.js').ObjectLayerModel} */
454
- const ObjectLayer = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayer;
454
+ const ObjectLayer = DataBaseProviderService.getModel("ObjectLayer", options);
455
455
 
456
456
  // GET /generate-webp/:itemType/:itemId/:directionCode - Generate webp animation from PNG frames
457
457
  const itemType = req.params.itemType;
@@ -515,7 +515,10 @@ class ObjectLayerService {
515
515
 
516
516
  logger.info(`Executing command: ${cmd}`);
517
517
 
518
- const result = shellExec(cmd, { silent: false });
518
+ // silentOnError so we can build a domain-specific Error with the
519
+ // captured stderr/stdout context (callers want a friendly message,
520
+ // not a generic ShellExecError).
521
+ const result = shellExec(cmd, { silent: false, silentOnError: true });
519
522
 
520
523
  if (result.code !== 0) {
521
524
  throw new Error(`img2webp command failed: ${result.stderr || result.stdout}`);
@@ -586,7 +589,7 @@ class ObjectLayerService {
586
589
  */
587
590
  static put = async (req, res, options) => {
588
591
  /** @type {import('./object-layer.model.js').ObjectLayerModel} */
589
- const ObjectLayer = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayer;
592
+ const ObjectLayer = DataBaseProviderService.getModel("ObjectLayer", options);
590
593
 
591
594
  // PUT /:id/frame-image/:itemType/:itemId/:directionCode - Update frame images for specific direction
592
595
  if (req.path.includes('/frame-image/')) {
@@ -686,7 +689,7 @@ class ObjectLayerService {
686
689
  fs.writeFileSync(`${publicFolder}/metadata.json`, metadataContent);
687
690
 
688
691
  const ObjectLayerRenderFrames =
689
- DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayerRenderFrames;
692
+ DataBaseProviderService.getModel("ObjectLayerRenderFrames", options);
690
693
 
691
694
  // Build object layer data from the asset directory
692
695
  const { objectLayerRenderFramesData, objectLayerData } =
@@ -803,9 +806,9 @@ class ObjectLayerService {
803
806
  */
804
807
  static delete = async (req, res, options) => {
805
808
  /** @type {import('./object-layer.model.js').ObjectLayerModel} */
806
- const ObjectLayer = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayer;
809
+ const ObjectLayer = DataBaseProviderService.getModel("ObjectLayer", options);
807
810
  const ObjectLayerRenderFrames =
808
- DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayerRenderFrames;
811
+ DataBaseProviderService.getModel("ObjectLayerRenderFrames", options);
809
812
 
810
813
  if (req.params.id) {
811
814
  // Load the full object layer so we can access all references
@@ -4,24 +4,28 @@ import express from 'express';
4
4
 
5
5
  const logger = loggerFactory(import.meta);
6
6
 
7
- const ObjectLayerRenderFramesRouter = (options) => {
8
- const router = express.Router();
9
- const authMiddleware = options.authMiddleware;
10
- router.post(`/:id`, async (req, res) => await ObjectLayerRenderFramesController.post(req, res, options));
11
- router.post(`/`, async (req, res) => await ObjectLayerRenderFramesController.post(req, res, options));
12
- router.get(
13
- `/:id`,
14
- // authMiddleware,
15
- async (req, res) => await ObjectLayerRenderFramesController.get(req, res, options),
16
- );
17
- router.get(`/`, async (req, res) => await ObjectLayerRenderFramesController.get(req, res, options));
18
- router.put(`/:id`, async (req, res) => await ObjectLayerRenderFramesController.put(req, res, options));
19
- router.put(`/`, async (req, res) => await ObjectLayerRenderFramesController.put(req, res, options));
20
- router.delete(`/:id`, async (req, res) => await ObjectLayerRenderFramesController.delete(req, res, options));
21
- router.delete(`/`, async (req, res) => await ObjectLayerRenderFramesController.delete(req, res, options));
22
- return router;
23
- };
7
+ class ObjectLayerRenderFramesRouter {
8
+ /**
9
+ * @param {import('../types.js').RouterOptions} options
10
+ * @returns {import('express').Router}
11
+ */
12
+ static router(options) {
13
+ const router = express.Router();
14
+ router.post(`/:id`, async (req, res) => await ObjectLayerRenderFramesController.post(req, res, options));
15
+ router.post(`/`, async (req, res) => await ObjectLayerRenderFramesController.post(req, res, options));
16
+ router.get(`/:id`,
17
+ // options.authMiddleware,
18
+ async (req, res) => await ObjectLayerRenderFramesController.get(req, res, options),
19
+ );
20
+ router.get(`/`, async (req, res) => await ObjectLayerRenderFramesController.get(req, res, options));
21
+ router.put(`/:id`, async (req, res) => await ObjectLayerRenderFramesController.put(req, res, options));
22
+ router.put(`/`, async (req, res) => await ObjectLayerRenderFramesController.put(req, res, options));
23
+ router.delete(`/:id`, async (req, res) => await ObjectLayerRenderFramesController.delete(req, res, options));
24
+ router.delete(`/`, async (req, res) => await ObjectLayerRenderFramesController.delete(req, res, options));
25
+ return router;
26
+ }
27
+ }
24
28
 
25
- const ApiRouter = ObjectLayerRenderFramesRouter;
29
+ const ApiRouter = (options) => ObjectLayerRenderFramesRouter.router(options);
26
30
 
27
31
  export { ApiRouter, ObjectLayerRenderFramesRouter };
@@ -1,4 +1,4 @@
1
- import { DataBaseProvider } from '../../db/DataBaseProvider.js';
1
+ import { DataBaseProviderService } from '../../db/DataBaseProvider.js';
2
2
  import { loggerFactory } from '../../server/logger.js';
3
3
  import { DataQuery } from '../../server/data-query.js';
4
4
 
@@ -8,13 +8,13 @@ class ObjectLayerRenderFramesService {
8
8
  static post = async (req, res, options) => {
9
9
  /** @type {import('./object-layer-render-frames.model.js').ObjectLayerRenderFramesModel} */
10
10
  const ObjectLayerRenderFrames =
11
- DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayerRenderFrames;
11
+ DataBaseProviderService.getModel("ObjectLayerRenderFrames", options);
12
12
  return await new ObjectLayerRenderFrames(req.body).save();
13
13
  };
14
14
  static get = async (req, res, options) => {
15
15
  /** @type {import('./object-layer-render-frames.model.js').ObjectLayerRenderFramesModel} */
16
16
  const ObjectLayerRenderFrames =
17
- DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayerRenderFrames;
17
+ DataBaseProviderService.getModel("ObjectLayerRenderFrames", options);
18
18
  if (req.params.id) return await ObjectLayerRenderFrames.findById(req.params.id);
19
19
 
20
20
  // Parse query parameters using DataQuery helper
@@ -31,13 +31,13 @@ class ObjectLayerRenderFramesService {
31
31
  static put = async (req, res, options) => {
32
32
  /** @type {import('./object-layer-render-frames.model.js').ObjectLayerRenderFramesModel} */
33
33
  const ObjectLayerRenderFrames =
34
- DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayerRenderFrames;
34
+ DataBaseProviderService.getModel("ObjectLayerRenderFrames", options);
35
35
  return await ObjectLayerRenderFrames.findByIdAndUpdate(req.params.id, req.body);
36
36
  };
37
37
  static delete = async (req, res, options) => {
38
38
  /** @type {import('./object-layer-render-frames.model.js').ObjectLayerRenderFramesModel} */
39
39
  const ObjectLayerRenderFrames =
40
- DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.ObjectLayerRenderFrames;
40
+ DataBaseProviderService.getModel("ObjectLayerRenderFrames", options);
41
41
  if (req.params.id) return await ObjectLayerRenderFrames.findByIdAndDelete(req.params.id);
42
42
  else return await ObjectLayerRenderFrames.deleteMany();
43
43
  };
@@ -4,18 +4,23 @@ import express from 'express';
4
4
 
5
5
  const logger = loggerFactory(import.meta);
6
6
 
7
- const TestRouter = (options) => {
8
- const router = express.Router();
9
- const authMiddleware = options.authMiddleware;
10
- router.post(`/:id`, async (req, res) => await TestController.post(req, res, options));
11
- router.post(`/`, authMiddleware, async (req, res) => await TestController.post(req, res, options));
12
- router.get(`/:id`, async (req, res) => await TestController.get(req, res, options));
13
- router.get(`/`, async (req, res) => await TestController.get(req, res, options));
14
- router.delete(`/:id`, async (req, res) => await TestController.delete(req, res, options));
15
- router.delete(`/`, async (req, res) => await TestController.delete(req, res, options));
16
- return router;
17
- };
7
+ class TestRouter {
8
+ /**
9
+ * @param {import('../types.js').RouterOptions} options
10
+ * @returns {import('express').Router}
11
+ */
12
+ static router(options) {
13
+ const router = express.Router();
14
+ router.post(`/:id`, async (req, res) => await TestController.post(req, res, options));
15
+ router.post(`/`, options.authMiddleware, async (req, res) => await TestController.post(req, res, options));
16
+ router.get(`/:id`, async (req, res) => await TestController.get(req, res, options));
17
+ router.get(`/`, async (req, res) => await TestController.get(req, res, options));
18
+ router.delete(`/:id`, async (req, res) => await TestController.delete(req, res, options));
19
+ router.delete(`/`, async (req, res) => await TestController.delete(req, res, options));
20
+ return router;
21
+ }
22
+ }
18
23
 
19
- const ApiRouter = TestRouter;
24
+ const ApiRouter = (options) => TestRouter.router(options);
20
25
 
21
26
  export { ApiRouter, TestRouter };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @module src/api/types
3
+ * @description Shared type definitions for the Express router layer.
4
+ */
5
+
6
+ /**
7
+ * Injected dependencies and runtime configuration for every API router instance.
8
+ * Keyed per-host/path by the multi-tenant engine (see src/runtime/express/Express.js).
9
+ *
10
+ * @typedef {Object} RouterOptions
11
+ * @property {import('express').Application} app - Express application instance.
12
+ * @property {string} host - Per-runtime host identifier (e.g. "nexodev.org").
13
+ * @property {string} path - Per-runtime path prefix (e.g. "/" or "/cyberia").
14
+ * @property {string} apiPath - Computed base URL for the API layer.
15
+ * @property {string[]} origins - Allowed origins for CORS validation.
16
+ * @property {import('express').RequestHandler} authMiddleware - Dynamically generated JWT auth middleware (keyed by host+path).
17
+ * @property {Object} [db] - DataBaseProviderService configuration or instance reference.
18
+ * @property {Object} [mailer] - MailerProvider configuration or instance reference.
19
+ * @property {Object} [png] - Cached mailer image buffers (populated by UserRouter on first load).
20
+ * @property {Record<string, Buffer>} [png.buffer] - Map of image key to raw PNG buffer.
21
+ * @property {Function} [png.header] - Sets CORS/Content-Type response headers for PNG responses.
22
+ */
23
+
24
+ export { };
@@ -22,12 +22,13 @@ const _guestTtlMs = () => {
22
22
  */
23
23
  const buildGuestUser = (options) => {
24
24
  const now = new Date().toISOString();
25
- const _id = new mongoose.Types.ObjectId().toString();
25
+ const objectId = new mongoose.Types.ObjectId().toString();
26
26
  const role = 'guest';
27
+ const username = `${role}${objectId.slice(-5)}`;
27
28
  return {
28
- _id: `${role}${_id}`,
29
- username: `${role}${_id.slice(-5)}`,
30
- email: `${_id}@${options.host || 'localhost'}`,
29
+ _id: `${role}${objectId}`,
30
+ username,
31
+ email: `${username}@${options.host || 'localhost'}`,
31
32
  password: hashPassword(process.env.JWT_SECRET),
32
33
  role,
33
34
  emailConfirmed: false,